苏州网站设计公司兴田德润好不好,网站备案检验单,WordPress 多用户数据,开发app和网站的公司系列文章目录 欢迎大家订阅《计算机底层原理》、《自顶向下看Java》专栏、能够帮助到大家就是对我最大的鼓励、我会持续为大家输出优质内容#xff0c;敬请期待#xff01; 系列文章目录 文章目录 前言 一、抽象类 什么是抽象类#xff1f; 为什么要使用抽象类#xff1f; …系列文章目录 欢迎大家订阅《计算机底层原理》、《自顶向下看Java》专栏、能够帮助到大家就是对我最大的鼓励、我会持续为大家输出优质内容敬请期待 系列文章目录 文章目录 前言 一、抽象类 什么是抽象类 为什么要使用抽象类 抽象类和普通类有什么区别 拓展为什么抽象方法不可以使用static来修饰 二、接口 1.定义接口 2.接口特性 3.多接口实现 4.接口继承 5.使用接口实例化对象 6.静态方法 总结 前言 这篇文章将为大家重点讲解有关Java当中的抽象类和接口的知识全方位无死角带你彻底掌握抽象类和接口当中的重要知识点。 一、抽象类 什么是抽象类 在Java当中抽象类Abstract Class是一种不能够实例化的类、他的目的是为了被其他的类继承而设计的抽象类可以包含抽象方法也可以包含普通方法。 抽象方法是一种没有实现体的方法它只有方法签名而没有方法体、继承这个抽象类的子类必须实现这个抽象类当中的所有抽象方法如果不实现的话那么就意味着这个子类继承来父类的抽象方法而没有实现这些抽象方法就说明这个子类也是抽象类那么子类必须也使用abstract修饰。 定义抽象类的关键字是abstract定义抽象方法的关键字也是abstract一个类如果包含抽象方法那么这个类必须声明为抽象类。 package Yangon;abstract public class Person {private int age;abstract public void Print();
}
class Student extends Person{Overridepublic void Print() {System.out.println(Hello World!);}
}
class Main{public static void main(String[] args) {Student student new Student();student.Print();Person person new Student();person.Print();}
} 抽象类是不可以被实例化的只能通过它的子类对象当中的重写方法来进行调用。在面向对象的概念当中所有的对象都需要通过类来描述但是并不是所有的类都是用来描述对象的有些类仅仅为了提供一种使用规范这个类当中并没有足够的信息来描述这个类吗就比如我定义了一个抽象类Animal这个类当中定义了很多的抽象方例如 eat() 方法、sleep()方法所有的动物对象都会吃饭并且睡觉这些方法我全部定义成为抽象方法不提供具体实现因为不同的动物虽然都会进行这些动作但是不同的动物再进行这些动作的时候状态是不一样的例如是站着睡觉的而就是躺着睡觉的所以Animal抽象类当中的抽象方法是不可以提供具体实现的只能够被具体的子类继承并且重写这些抽象方法的时候才可以实现这些方法。 abstract class Animal{abstract public void eat();abstract public void sleep();
}
class Dog extends Animal{Overridepublic void eat() {System.out.println(吃狗粮);}Overridepublic void sleep() {System.out.println(躺着睡);}
}
class Horse extends Animal{Overridepublic void eat() {System.out.println(吃牧草);}Overridepublic void sleep() {System.out.println(站着睡);}
} 为什么要使用抽象类 我们从代码的效果来看的话继承是完全可以解决这些问题的那么为什么要使用抽象类呢继承确实是一种实现代码重用和多态性的方式但并不一定非要使用抽象类、抽象类和继承是相关的概念但他们有不同的目的和用途。 1.目的不同抽象类的目的是为了作为其他类的基类提供一个通用的模板抽象类可以包含抽象方法这些方法需要在子类中被具体实现通过继承抽象类子类必须实现这些抽象方法通过强制子类实现从而确保子类具有一定的行为抽象类还可以包含具体方法这些方法可以在子类当中直接继承或者重写。 2.机制不同继承是代码重用的一种机制但是它不一定需要使用抽象类你可以使用普通的类继承来获得代码重用的好处抽象类的主要优势是它可以包含抽象方法而这些方法在子类当中必须被实现从而强制执行一定的约定。 我们在选择使用抽象类还是普通类或者是我们一会要提到的接口取决于我们的具体需求如果我们希望提供一个通用的模板、并且要求子类必须实现特定的方法那么抽象类是一个合适的选择如果我们更关注行为的规范而不是具体的实现接口可能是更好的选择接口我稍后会为大家具体讲解但是如果我们想要使用普通类来继承实现代码重用的话一定要注意继承普通类的确是一种有效的代码重用方式但是要注意避免深度继承和过度耦合。 抽象类的访问限定符有什么意义 1.public抽象类可以被其他任何类访问对的是任何类。 2.protected只能被子类和同一个包内的所有类访问。 3.default这个时候只能被同一包内的类访问。 4.private抽象类不可以使用private来修饰因为抽象类的目的就是为了被继承但是private是不可以被继承的所以这与抽象类的设计初心相违背所以不允许。 那么抽象方法使用访问限定符的规则与普通方法完全一样这里就不做特别的声明了。注意一点抽象方法也不可以被声明为private因为这个方法也是必须被子类继承并且实现的。 抽象类和普通类有什么区别 抽象类和普通类在Java当中的实现是非常类似的他们都会被编译成为字节码并且在Java虚拟机当中执行以下我为大家列举出一些相似点和区别点。 相似点 1.字节码生成抽象类和普通类都会生成字节码文件、其中包含了类的结构、字段、方法等信息。 2.内存管理对象的内存分配和释放由Java虚拟机进行管理这对于抽象类和普通类都是一样的他们都会存储在JVM的方法区当中。 3.方法调用对象的方法调用采用虚方法调用的方式确保在运行时根据对象的实际类型进行动态绑定来实现多态关于动态绑定和多态的知识点我在上一篇文章已经详细地介绍过了如果大家需要可以去看我之前的文章这里就不做赘述了。 区别点 1.实例化抽象类不能实例化但是普通类可以直接实例化抽象类需要通过子类实现并且实例化。 2.构造器抽象类也可以有构造器、用于初始化抽象类的实例、普通类也有构造器、但是抽象类的构造器不能够直接实例化抽象类而是由子类的构造器来进行调用。 3.抽象方法抽象类可以包含抽象方法这是一种声明但是不实现的方法普通类可以包含抽象方法但是不需要。 从底层的视角来看的话抽象类其实和普通类没有太大的区别Java编译器和JVM在处理抽象类和普通类时并没有太大的区别它们都会被翻译成为相应的字节码然后在虚拟机上执行。抽象类主要提供了一种面向对象的设计机制强制要求子类实现抽象方法而相比于抽象类普通类会更加地灵活可以直接实例化 拓展为什么抽象方法不可以使用static来修饰 首先我先为大家讲解一下抽象方法和静态方法的区别 静态方法使用static关键字来进行修饰在编译时会同类的结构信息一同加载到方法区当中所以静态方法的调用是依赖于类的属于类级别而不依赖于类的实例同样静态方法是不可以访问类的实例成员和变量只能访问类的静态成员和变量而静态方法可以被继承但是它不会被子类重写如果子类定义了与父类同名的静态方法子类当中的静态方法不会覆盖父类当中的静态方法最重要的一点就是静态方法是不具备多态性的他在编译时就可以确定方法调用的目标。 但是反观抽象类抽象类被abstract修饰在抽象的父类当中声明并且必须在子类当中提供实现然后通过子类的对象实例调用可以访问父类当中的实例成员和变量抽象方法和普通方法一样都具有多态性可以被继承可以被重写通过向上转型就可以实现多态。 其实我说到了这里大家应该也已经明白了为什么抽象方法不能够被static修饰因为抽象方法和静态方法在设计理念上就是相违背的这里还要多提一句抽象方法也不能够被final修饰因为抽象方法必须被子类重写。 二、接口 Java中接口是一种抽象数据类型用于定义一组抽象方法、但是不提供方法的具体实现接口允许类实现这些抽象方法并在类中提供实现。 1.定义接口 使用interface关键字来定义接口接口当中包括抽象方法、常量要注意这里的常量被隐式地指定为public static final以及默认方法和静态方法。 抽象方法首先说到抽象方法接口当中的抽象方法就是没有方法体的方法只有方法签名实现接口的类必须提供这些方法的具体实现。这里要专门提一句接口当中的抽象方法会被隐式地修饰成为public abstract所以接口当中的方法定义不需要很复杂。 变量常量在接口当中声明的所有变量都是常量都会被编译器隐式地修饰成为public static final类型因为接口就是需要被实现的所以使用public这些接口当中的变量实际上是常量必须被初始化并且在类当中不可以被修改。 默认方法从Java8 开始引入默认方法是在接口中包含方法体的方法、他们允许在接口当中添加新的方法而不会破坏实现这个接口的类。 静态方法静态方法是在接口当中使用static关键字定义的方法。 interface IPrint{void Print();default void Func(){System.out.println(Hello default Func());}int I_Value 10;static void StaticFunc(){System.out.println(Hello static Func());}
}
class Student2 implements IPrint{Overridepublic void Print() {System.out.println(Hello Print());}Overridepublic void Func() {//IPrint.super.Func(); 调用接口当中原本的默认方法System.out.println(我重写了父类的默认方法);}public static void main(String[] args) {IPrint iPrint new Student2();iPrint.Func();iPrint.Print();System.out.println(I_Value);}
}拓展 很多的小伙伴可能第一次听说接口的默认方法的概念那么什么是默认方法呢默认方法的引入是为了在接口当中添加新的方法而不会影响这个接口的已有类也就是说如果我定义了一个接口并且已经使用类对他进行实现但是这个时候我发现这个接口并不完善想要在这个接口当中补充一些新的方法可是如果我们继续定义抽象方法的话那就意味着凡是实现过这个接口的类都必须实现这个新增的方法也就是牵一发而动全身非常的麻烦所以也就引入了默认方法在Java8之前一旦一个接口当中定义了新的方法所有实现该接口的类都必须提供该方法的实现否则就会编译报错。 默认方法通过在接口当中直接提供方法体使得接口可以包含具体的方法实现这样实现接口的类如果没有显式提供对默认方法的实现那么就会使用接口当中的默认实现这位接口的演进提供了一种向后兼容的方式。 在实现类当中如果希望使用默认方法提供的实现可以直接继承接口当中的默认方法如果需要覆盖默认方法可以在实现类中重新实现该方法。 这种设计的好处在于当接口需要添加新的方法的时候不会破坏已有的实现类因为它们可以选择是否提供新的方法而不会强制所有类都做出修改这有助于在不破坏现有代码的情况下为接口添加新的功能增强接口的灵活性。 interface IWork{void eat();int I_Value 10;default void print(){System.out.println(接口当中的常量 I_Value);}
}
public class Animal {private String name;
}
class Dog extends Animal implements IWork{Overridepublic void eat() {}Overridepublic void print() {IWork.super.print();}
}如上面的代码所示接口当中定义了默认方法如果类当中没有明确重写这个接口当中的默认方法那么默认还使用接口当中原本定义的默认方法大家可以运行一下看看效果。 这里要提示一下大家可能会有小伙伴认为既然是默认方法那么这个default访问权限不写也可以他还是默认方法这是绝对不可以的这里的default关键字必须加上这是Java8之后独有的特性就是为了和抽象方法做区分如果不写的话编译器会自动将其识别为public abstract的抽象方法。 2.接口特性 接口并不能直接使用必须有一个类来实现它实现的关系通过关键字implements来完成。 1.接口类型是一种引用类型不能直接使用new关键字来实例化接口。、 2.接口当中的每一个没有实现的方法都是public的抽象方法即接口当中的方法会被隐式地指定为public abstract当然我刚才提到的默认方法是Java8之后的一个特性大家在这里自行做一个区分。 3.接口当中的方法是不能在接口当中实现的只能由类来实现。 4.当我们重写接口当中的方法的时候只能使用public访问权限注意这里非常重要即便是重写接口当中的默认方法也只能使用public修饰因为接口就是为了提供一种规范供所有人使用即便是默认方法也是为了让大家去实现的所以重写接口的方法必须是public修饰。 5.接口当中的变量会被隐式地指定为public static final变量说白了也就是常量接口当中定义的变量其实都是常量编译器不允许修改还是之前的原因接口就是为了提供一种规范如果接口当中的属性可以随意修改那就乱套了大家都知道秦始皇同意度量衡书同文、车同轨就是为了提供一种规范那么大家觉得这种规范我们作为程序员可以随意修改吗显然是不行的。 6.接口当中不可以有静态代码块和构造方法。首先我们先说为什么不能定义构造方法很简单大家还记得构造函数的作用是什么吗是不是就是为了实例化对象的时候为这个实例化对象进行初始化的这就是构造函数的作用那么接口是不可以被实例化的他就是一个规范那么这样不能够被实例化的接口提供构造函数有什么意义呢 那么我们再谈为什么接口当中不能够定义静态代码块呢首先我先说结论不只是静态代码块即使是普通代码块接口当中也不可以定义接口当中主要为了提供一套规范用于定义抽象方法、常量默认方法和静态方法。这些都是属于静态绑定在程序的编译期间就已经绑定和确认了在接口当中定义静态代码块和普通代码块它们根本就没有执行的时机况且接口属于类级别编译后会加载到方法区内但是普通代码块是在实例化对象的时候执行的它们属于实例的初始化阶段属于对象的初始化过程而接口不能够被初始化所以自然也就不能定义普通代码块静态代码块自然也不行虽然静态代码块不依赖于对象的实例但是接口的存在就是为了提供一套规范并不是为了执行某种逻辑存在的所以在接口当中定义代码块不论是什么类型的代码块都是不被允许的。 7.接口虽然不是类但是接口编译完成后的字节码文件的后缀格式也是.class。 8.如果类没有实现接口中的抽象方法则类必须设置为抽象类。 9.接口当中还可以包含default方法刚才已经讲过了。 3.多接口实现 我们都知道类和类之间是单继承的一个类只允许有一个父类但是接口不一样Java当中不支持多继承但是一个类当中是可以有多个接口的也就是说一个类可以实现多个接口。 interface IFly{void fly();
}
interface IRun{void run();
}
public class Animal implements IFly,IRun{Overridepublic void fly() {System.out.println(我会飞);}Overridepublic void run() {System.out.println(我会跑);}
} 多继承的实现代码已经给大家展示出来了就这些内容。 4.接口继承 在Java当中类和类之间是单继承的一个类可以实现多个接口接口于接口之间可以多继承接口之间的继承同样也是extends来实现的。我用一段代码来为大家展示一下接口之间的继承这段代码里面涉及到了默认方法所以大家需要将我之前讲的有关默认方法的知识全部吸收否则这里会理解困难。 package Demo2;interface Interface1{void method1();default void defaultMethod(){System.out.println(Default method in Interface1);}
}
interface Interface2{void method2();default void defaultMethod2(){System.out.println(Default method in Interface2);}
}
interface ExtendsInterface extends Interface1,Interface2{void additionalMethod();Overridedefault void defaultMethod() {//Interface1.super.defaultMethod();System.out.println(我重写了第一个接口当中的默认方法);}Overridedefault void defaultMethod2() {//Interface2.super.defaultMethod2();System.out.println(我重写了第二个接口当中的默认方法);}
}
class MyClass implements ExtendsInterface{Overridepublic void method1() {System.out.println(这个类实现了接口当中的method1()方法);}Overridepublic void method2() {System.out.println(这个类实现了接口当中的method2()方法);}Overridepublic void additionalMethod() {System.out.println(这个类当中实现了接口当中的method2()方法);}
}
public class Main {public static void main(String[] args) {MyClass myClassObj new MyClass();myClassObj.method1();myClassObj.method2();myClassObj.additionalMethod();myClassObj.defaultMethod();myClassObj.defaultMethod2();}
} 5.使用接口实例化对象 使用接口的实例化类似于多态通过向上转型来访问子类重写父类的方法一个类实现了这个接口通过向上转型就可以访问类重写接口的方法整体的用法类似于多态。这里就不进行过多地赘述了。 这里再为大家展示出一份相较于之前更为完整的一份代码。 package Demo2;interface Interface1{void method1();default void defaultMethod(){System.out.println(Default method in Interface1);}
}
interface Interface2{void method2();default void defaultMethod2(){System.out.println(Default method in Interface2);}
}
interface ExtendsInterface extends Interface1,Interface2{void additionalMethod();Overridedefault void defaultMethod() {//Interface1.super.defaultMethod();System.out.println(我重写了第一个接口当中的默认方法);}Overridedefault void defaultMethod2() {//Interface2.super.defaultMethod2();System.out.println(我重写了第二个接口当中的默认方法);}
}
class MyClass implements ExtendsInterface{Overridepublic void method1() {System.out.println(这个类实现了接口当中的method1()方法);}Overridepublic void method2() {System.out.println(这个类实现了接口当中的method2()方法);}Overridepublic void additionalMethod() {System.out.println(这个类当中实现了接口当中的额外默认方法);}Overridepublic void defaultMethod(){System.out.println(在继承接口重写的基础之上我又一次重写了第一个接口的默认方法);}Overridepublic void defaultMethod2(){System.out.println(在继承接口重写的基础之上我又一次重写了第二个接口的默认方法);}
}
public class Main {public static void main(String[] args) {MyClass myClassObj new MyClass();myClassObj.method1();myClassObj.method2();myClassObj.additionalMethod();myClassObj.defaultMethod();myClassObj.defaultMethod2();System.out.println();ExtendsInterface extendsInterfaceObj new MyClass();extendsInterfaceObj.additionalMethod();extendsInterfaceObj.defaultMethod();extendsInterfaceObj.defaultMethod2();}
}6.静态方法 Java8以及更高的更新版本使用接口的时候我们可以在接口当中定义静态方法这些静态方法是于接口本身相关的而不是于实现接口的类相关的。 interface IUsb{static void Print(){System.out.println(Hello World!);}
} 静态方法不需要再类当中实现可以直接通过接口的名称来进行调用这些静态方法不需要创建接口的实例。使用这种方式接口可以提供一些于接口本身直接相关的使用方法而不必依赖于实现类的实例这对于定义一些通用的辅助或工具方法非常有用。 public class Main {public static void main(String[] args) {IUsb.Print();}
}
interface IUsb{static void Print(){System.out.println(Hello World!);}
}代码如上图所示这就是接口当中的抽象类静态方法的使用方式就为大家介绍到这里。 总结 Java当中抽象类和接口就为大家介绍到这里还有关于深浅拷贝和Object类的相关内容我放到下一篇文章再去讲解离过年不远了我也要准备开始我的《编译原理》专栏的准备工作了争取在阴历年前把编译原理的所有重点全部系统地整理出来真的很久没有用心地去准备做一件事情了自律的快乐超过了所有物质享受给我带来的快乐各位小伙伴们一起加油