-
2019-05-30 18:15:44
一、抽象类
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就可以称之为抽象类。
1.抽象方法:使用abstract修饰且没有方法体的方法。
特点:
① 抽象方法没有方法体,交给子类实现
② 抽象方法修饰符不能是private final static
③ 抽象方法必须定义在抽象类或者接口中
2.抽象类:包含抽象方法的类,即使用abstract修饰的类。
特点:
① 抽象类不能被实例化,只能被继承
② 抽象类中可以不包含抽象方法(不包含抽象方法就没有太大意义,可以作为工具类防止被实例化)
③ 抽象类的子类可以不实现该类所有的抽象方法,但也必须作为抽象类(抽象派生类)
④ 抽象类的构造方法不能定义成私有(子类构造方法会调用父类构造方法)
⑤ 抽象类不能使用final修饰,final修饰的类不能被继承
实例:武器作为一个抽象类具备攻击行为(attack方法),具体如何攻击(how2Attack方法)需要子类实现。如:机关枪可以射击敌人,手榴弹可以丢向敌人。
public class Test3 { public static void main(String[] args) { Gun gun = new Gun("机关枪"); Grenade grenade = new Grenade("手榴弹"); gun.attack(); grenade.attack(); gun.how2Attack(); grenade.how2Attack(); } } abstract class Weapon{ String name; public void attack(){ System.out.println(name+"具有攻击行为"); } abstract void how2Attack(); } class Gun extends Weapon{ public Gun(String name) { this.name = name; } @Override void how2Attack() { System.out.println(name+"射击敌人"); } } class Grenade extends Weapon{ public Grenade(String name){ this.name = name; } @Override void how2Attack() { System.out.println(name+"丢向敌人"); } }
二、接口
1.什么是接口:
① 硬件接口:是指同一计算机不同功能层之间的通信规则称为接口。
② 软件接口:是指对协定进行定义的引用类型。其他类型实现接口,以保证它们支持某些操作。
2.Java中的接口:在JAVA编程语言中是接口一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
特点:
① 接口中没有构造器,不能被实例化
② 接口只能继承接口,不能继承类,接口支持多继承
③ 接口中的定义的成员变量,默认是public static final修饰的静态常量
④ 接口中定义的方法,默认是public abstract修饰的抽象方法
⑤ 接口中定义的内部类,默认是public static修饰的静态内部类
标志接口:仅仅作为一个定义,就是一个标志
常量接口:用来封装多个常量信息
注意:在JDK8中,接口也可以定义静态方法和默认非静态方法,可以直接用接口名调用静态方法,实现类可以调用默认非静态方法。如果同时实现两个接口,接口中定义了一样的默认方法,则实现类必须重写默认方法,不然会报错。
实例:走路和游泳作为两个抽象的行为,青蛙可以实现两个行为接口来具体实现行为的内容
public class Test4 { public static void main(String[] args) { Frog frog = new Frog("青蛙"); frog.getName(); frog.work(); frog.swim(); } } class Animal { String name; public String getName() { System.out.println("Animal:"+name); return name; } public void setName(String name) { this.name = name; } } interface IWalk{ void work(); } interface ISwim{ void swim(); } class Frog extends Animal implements IWalk,ISwim{ public Frog(String name) { this.name = name; } @Override public void work() { System.out.println(this.name+":蹦蹦跳跳地走路"); } @Override public void swim() { System.out.println(this.name+":在水里蛙泳"); } }
三、抽象类和接口的异同点
1.语法层面
相同点:
① 抽象类和接口都不能被实例化
② 抽象类和接口都可以定义抽象方法,子类/实现类必须覆写这些抽象方法
不同点:
① 抽象类有构造方法,接口没有构造方法
② 抽象类可以包含普通方法,接口中只能是public abstract修饰抽象方法(Java8之后可以)
③ 抽象类只能单继承,接口可以多继承
④ 抽象类可以定义各种类型的成员变量,接口中只能是public static final修饰的静态常量
2.设计层面
① 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。
② 设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
四、抽象类和接口的使用场景
1.抽象类的使用场景
既想约束子类具有共同的行为(但不再乎其如何实现),又想拥有缺省的方法,又能拥有实例变量
如:模板方法设计模式,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中某些步骤的具体实现。
2.接口的应用场景
① 约束多个实现类具有统一的行为,但是不在乎每个实现类如何具体实现
② 作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。
③ 实现类需要具备很多不同的功能,但各个功能之间可能没有任何联系。
④ 使用接口的引用调用具体实现类中实现的方法(多态)
个人见解,若有错误请指出,谢谢!
更多相关内容 -
Java中的抽象类和接口
2022-04-08 15:17:42各位铁汁们大家好呀!今天让我们继续学习java,看看java中的抽象类和接口到底是什么? 里面也会讲到多态呀,一起来看看吧目录
各位铁汁们大家好呀😊!
😎今天让我们继续学习java,看看java中的抽象类和接口到底是什么🤔?
什么是抽象类
🍑我们之前学过什么是类,那么抽象类是不是也是类的一种呢?
听名字就感觉好抽象呀!说对了,他就是抽象的,不是具体的。在类中没有包含足够的信息来描绘一个具体的对象,这样的类称为抽象类。
🌰来看一个抽象类的例子
// 抽象类和抽象方法需要被 abstract 关键字修饰 abstract class Shape { // 抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体 abstract void draw(); }
大家觉得这个抽象类是不是什么也没干,他唯一的方法draw()还是空的。
像这样的类是不是就没有包含足够的信息来描绘一个具体的对象,自然也就不能实例化对象了。不信你看:
🍑那既然一个类不能实例化,那这种抽象类存在的意义是什么呀🤔?别急,存在即合理,听我慢慢道来。
抽象类在实现多态中的意义
🍑抽象类存在的一个最大意义就是被继承,当被继承后就可以利用抽象类实现多态。
来看一段代码
// 抽象类和抽象方法需要被 abstract 关键字修饰 abstract class Shape { // 抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体 abstract void draw(); } // 当一个普通类继承一个抽象类后,这个普通类必须重写抽象类中的方法 class Cycle extends Shape { @Override void draw() { // 重写抽象类中的draw方法 System.out.println("画一个圆圈"); } } public class Test4 { public static void main(String[] args) { //Shape shape = new Shape(); 抽象类虽然不能直接实例化 // 但可以把一个普通类对象传给一个抽象类的引用呀,即父类引用指向子类对象 Shape shape = new Cycle(); // 这称作:向上转型 /*Cycle cycle = new Cycle(); Shape shape = cycle // 这是向上转型的另一种写法 */ shape.draw(); // 通过父类引用调用被子类重写的方法 } }
运行之后你就会发现神奇的一幕:
大家在看完了代码可能会有很多疑问,别急咱们一个一个的说,
📝什么是向上转型:一句话总结就是“父类引用指向子类对象”
向上转型后的变化
- 🏀关于方法:父类引用可以调用子类和父类公用的方法(如果子类重写了父类的方法,则调用子类的方法),但子类特有的方法无法调用。
- 🏀关于属性: 父类引用可以调用父类的属性,不可以调用子类的属性
向上转型的作用
- 🐟减少一些重复性的代码
- 🐟对象实例化的时候可以根据不同需求实例化不同的对象
🌰这样的话就我们上面的代码就可以理解了
📝看来,我们可以通过子类对抽象类的继承和重写,抽象类还真有点用呀!
🍑但这和多态有什么关系呢,抽象类用起来这么麻烦,我还不如直接用普通类,也能达到这样的效果,还不用再写一个子类呢😫?
🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟
🌰那行,你再看看下面的代码,你就知道抽象类在实现多态时的好处了。
abstract class Shape { public abstract void draw(); // 抽象方法不能里有具体的语句 } // 当一个普通类继承一个抽象类的时候,再这个子类中必须重写抽象类中的抽象方法 class Cycle extends Shape { @Override // 如果不重写会报错,但如果继承的是普通类则不会报错,用抽象类更安全 public void draw() { System.out.println("画一个圆圈"); } } class Flower extends Shape { // 不同的子类对父类的draw方法进行了不同的重写 @Override public void draw() { System.out.println("画一朵花"); } } class Square extends Shape { @Override public void draw() { System.out.println("画一个正方形"); } } public class Test4 { public static void main(String[] args) { Cycle cycle = new Cycle(); // 子类引用cycle Flower flower = new Flower(); // 子类引用flower Square square = new Square(); // 数组的类型是Shape,即数组中每一个元素都是一个父类引用 // 在这个过程其实也发生了向上转型,对抽象类中的方法进行了重写 Shape[] shapes = {cycle, flower, square}; // 父类引用引用不同的子类对象 for (int i = 0; i < shapes.length; i++) { Shape shape = shapes[i]; // 父类引用shape指向—>当前所对应的子类对象 shape.draw(); // 通过父类引用调用子类重写的draw方法 } } }
🍑调用同一个方法竟然打印出了不同的结果😮,这难道就是所谓的多态🤔
是不是有点懵😂,下面我们来解释一下😉
// 对上面的代码补充一下 // 可能你对 Shape[] shapes = {cycle, flower, square};不太理解 // 但上面的代码就相当于 Shape[] shapes1 = new Shape[3]; // 有三个不同的子类对象呀!数组大小为3 // (将指向->子类对象)的子类引用赋值给父类对象,不就相当于该夫类引用指向->所对应的子类对象吗 //这是向上转型的另一种写法,应为前面已经实例化了子类对象 Cycle cycle = new Cycle(); shapes1[0] = cycle; // 如果前面没实例化子类对象,就要写成shape1[0] = new Cycle shapes1[1] = flower; shapes1[2] = square;
对于多态来说,他有这三个要素
- 继承(我们刚才的Cycle类继承Shape抽象类)
- 重写(我们子类对draw方法的重写)
- 父类指向子类对象(就是shape1[0] = cycle -->也可以称作向上转型)
🍑回头再看一下我们的代码,是不是就刚好符合了多态的三要素😉。
📝当我们的父类引用指向不同的子类对象时,当我们调用同一个draw方法时却输出了不同的结果。(其实就是该方法再子类中被重写成了不同形式)这就叫做多态 。
嘻嘻😂,其实只要只要结合着例子来看,多态也没那么难理解呀😎
🍑那为啥一定要用抽象类呢😂?我一个普通类继承普通类来实现多态不可以吗🤔
🌰当然可以,但不太安全有风险;
但如果是抽象类的话,就不一样了😉
🍑从这我们也可以看出,当用抽象类的时候,编译器自动就对我们是否重写进行了校验,而充分利用编译器的校验, 在实际开发中是非常有意义的 。所以说抽象类还是有用的,嘻嘻😉
📝好了,相信到这里你对抽象类也有了一个大概的认识😊,下面我们来简单做一下总结
- 使用abstract修饰的类或方法,就抽象类或者抽象方法
- 抽象类是不能具体的描述一个对象,不能用抽象类直接实例化对象
- 抽象类里面的成员变量和成员方法,都是和普通类一样的,只不过就是不能进行实例化了
- 当一个普通类继承这个抽象类后,那么这个普通类必须重写抽象类当中的所有的抽象方法🤔(我们之前说过抽象类是不具体的,没有包含足够的信息来描述一个对象,所以我们需要把他补充完整)
- 但当一个抽象类A继承了抽象类B,这是抽象类A就可以不重写抽象类B当中的抽象方法
- final不能修饰抽象类和抽象方法(因为抽象类存在的最大意义就是被继承,而被final修饰的不能被继承,final和抽象,他们两个是天敌😂)
- 抽象方法不能被private修饰(抽象方法一般都是要被重写的,你被private修饰了,还怎么重写😫)
- 抽象类当中不一定有抽象方法,但如果一个类中有抽象方法,那么这个类一定是抽象类。
🌰哈哈,上面的8条总结是不是臭长臭长的,大家也不用专门去记(用的多了,自然就记住了😉)
🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟
接口是什么
🍑抽象类是从多个类中抽象出来的模板,如果将这种抽象进行的更彻底,则可以提炼出一种更加特殊的“抽象类”——接口(Interface)🤔。
📝接口是Java中最重要的概念之一,它可以被理解为一种特殊的类,不同的是接口的成员没有执行体,是由全局常量和公共的抽象方法所组成😎。
如何定义一个接口呢?下面我们来看一个栗子🌰
//接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口 public interface 接口名称{ // 定义变量 int a = 10; // 接口当中的成员变量默认都是public static final // 抽象方法 public abstract void method1(); // public abstract 是固定搭配,可以不写 void method2(); // 接口当中的成员方法默认都是public abstract, 更推荐用第二种来定义方法 }
可以看到接口和类其实还是有很多相似点:
📝接口中也包含抽象方法,所以也不能直接实例化接口🤔,那么我们怎么用接口呢?
🍑哈哈,很简单😉,我们再用一个普通类实现这个接口不就行了吗😂,不同的是抽象类是被子类来继承而实现的,而接口与类之间则是用关键字implements来实现。
📝就像普通类实现实现抽象类一样,一个类实现某个接口则必须实现该接口中的抽象方法,否则该类必须被定义为抽象类🤔。
通过接口实现多态
🍑铁汁们!刚才我们是用抽象类来实现多态,那么现在我们可以尝试用接口来实现多态,嘻嘻😎
接口可以看成是一种特殊的类,只能用 interface 关键字修饰 interface IShape { int a = 10; 接口当中的成员变量默认都是public static final int b = 23; void draw(); 接口当中的成员方法一般只能是抽象方法,默认是public abstract(JDK1.8以前) default void show() { System.out.println("接口中的其他方法");//接口中的其他方法也可以实现,但要用default修饰 } public static void test() { System.out.println("这是接口当中的一个静态的方法"); } } // 一个普通的类要想实现接口,可以用implement, //因为接口也是抽象方法的,所以实现接口的这个类也要重写抽象方法 class Cycle implements IShape { @Override public void draw() { System.out.println("画一个圆圈"); } } class Square implements IShape { @Override public void draw() { System.out.println("画一个正方形"); } } class Flower implements IShape { @Override public void draw() { System.out.println("画一朵花"); } } public class Test4 { public static void main(String[] args) { // IShape iShape = new IShape(); 接口也不能直接实例化 Cycle cycle = new Cycle(); Square square = new Square(); Flower flower = new Flower(); // 这里的IShape接口就相当与抽象类中父类,接口类型也是一种引用类型 IShape[] iShapes = {cycle, square, flower}; // 这个过程其实就发生了向上转型 for (IShape iShape : iShapes) { // 增强型的for—each循环,也可以写成普通的for循环形式 iShape.draw(); // 通过重写实现了多态 } } } 引用变量cycle和square都赋值给了Shape类型的引用变量shape, 但当执行shape.draw()时,java虚拟机到底要调用谁重写的的draw方法, 就看此时接口引用的是那个对象的,是shape的、还是cycle的
😎看一下运行结果😎
看完代码你可能有点晕😫,但没关系。一般接口咱也不这么用,直接使用抽象类不就好了😉(我只是演示一下用接口也能实现多态😂)
🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑
📝下面我们来总结一下Java中接口的几个主要特点
- 🌰接口中可以包含变量和方法,变量被隐式指定为 public static final,方法被隐式指定为 public abstract(JDK 1.8 d一个类可以同时实现多个接口,一个类实现某个接口则必须实现该接口中的抽象方法,否则该类必须被定义为抽象类
- 🌰接口支持多继承,即一个接口可以继承(extends)多个接口,间接解决了 Java 中类不能多继承的问题。
🍑那么接口一般用在什么地方呢?
- 一般情况下,实现类和它的抽象类之前具有 "is-a" 的关系,但是如果我们想达到同样的目的,但是又不存在这种关系时,使用接口。
- 由于 Java 中单继承的特性,导致一个类只能继承一个类,但是可以实现一个或多个接口,此时可以使用接口。
🌰下面就让我们来看看接口的正确用法:帮助java实现“ 多继承 ”😎
由于 Java 中单继承的特性,导致一个类只能继承一个类,但是可以实现一个或多个接口,此时可以使用接口。 class Animal { String name; // 不能使用private,后面的子类也要用 public Animal(String name) { // 父类的自定义的构造方法 this.name = name; } } interface IFlying { // 自定义多种接口 void fly(); } interface IRunning { void run(); } interface ISwimming { void swimming(); } // 小鸭子,不仅会跑,还会游泳、飞行 一个类继承父类,并实现多个接口,间接的解决java中不能多继承的问题 class Duck extends Animal implements IRunning, ISwimming, IFlying { public Duck(String name) { // 子类构造方法 super(name); // 必须在子类构造方法的第一行 // 在给实现子类的构造方法前,先要用super()调用实现父类的构造方法,比较先有父后有子呀! // 因为父类自己定义了构造方法,编译器不会自动给给子类构造方法中添加super();来实现父类的构造方法,需要我们自己实现 } // 对接口中的抽象方法进行重写 @Override public void fly() { System.out.println(this.name + "正在用翅膀飞"); } @Override public void run() { System.out.println(this.name + "正在用两条腿跑"); } @Override public void swimming() { System.out.println(this.name + "正在漂在水上"); } } public class 接口的使用 { // 不用学我用中文名作为类名,我只是为演示方便 public static void main(String[] args) { Duck duck = new Duck("第一个小鸭子"); // 实例化鸭子对象 duck.fly(); // 通过引用 变量名.方法名 输出重写后的方法 duck.run(); duck.swimming(); } } 有人可能会说干嘛用接口,我直接在父类Animal中实现fly、run、swimming这些属性, 然后不同的动物子类再继承父类这些方法不行吗? 但问题是,鸭子会fly、swimming,那猫会飞和游泳吗?你再写个其他动物的子类是不是就不行了 而用接口呢?我们只是把这种飞、游泳的行为给抽象出来了, 只要一个子类有这种行为,他就可以实现相对应的接口,接口是更加灵活的
📝上面的代码展示了 Java 面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多个接口。
📝继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性 ,能实现接口的类和该接口并不一定有is_a的关系,只要该类有这个接口的特性就行
猫是一种动物, 具有会跑的特性.
青蛙也是一种动物, 既能跑, 也能游泳
鸭子也是一种动物, 既能跑, 也能游, 还能飞
🍑这样设计有什么好处呢? 时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型,只要这个类有有这个特性就好。
举个栗子🌰
class Robot implements IRunning { private String name; public Robot(String name) { this.name = name; } // 对run方法进行重写 @Override public void run() { System.out.println("机器人" + this.name + "正在跑"); } } public class Test4 { public static void main(String[] args) { Robot robot1 = new Robot("图图"); robot1.run(); } } // 执行结果 机器人图图正在跑
😎只要能跑就行,管他是机器人还是动物呢😂,接口是不是很灵活呀!
同时在实际的开发过程中,一般来说,一个类是一个Java文件,一个接口也是一个Java文件。大家也要在平时就养成这个好习惯呀!
哈哈,不知道现在你对抽象类和接口的认识是不是又上升了一个高度呢?嘻嘻,我们下篇博客再见了,下篇让我们瞅瞅Java中常用的接口有哪些😉
每天进步一点点,铁汁们,一起加油😎😎😎
-
抽象类和接口
2020-11-24 19:38:35抽象类 概述 父类当中的方法,被他的子类们重写,子类的各自实现又不一样。那么父类的方法声明和方法体,只有声明还有意义,而方法体内容则没有存在的意义。我们把这种没有方法体内容的方法称为抽象方法。...抽象类
概述
父类当中的方法,被他的子类们重写,子类的各自实现又不一样。那么父类的方法声明和方法体,只有声明还有意义,而方法体内容则没有存在的意义。我们把这种没有方法体内容的方法称为抽象方法。Java语言规定,如果一个类包含了抽象的方法。那么该类就是一个抽象类
定义:
抽象方法:没有方法体的方法
抽象类:包含抽象方法的类
abstract关键字的使用格式
抽象方法
使用abstract关键字修饰成员方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
定义格式:
修饰符 abstract 返回值类型 方法名(参数列表);
示例代码:
public abstract void run(); // 吃饭的抽象方法 public abstract void eat(); // 跳跃的抽象方法 public abstract void jump();
抽象类
如果一个类包含了抽象方法,那么该类就是一个抽象类。
定义格式:
修饰符 abstract class ClassName {}
示例代码:
public abstract class Animal { // 奔跑的抽象方法 public abstract void run(); }
抽象的使用
继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为一个抽象类。
注意事项
关于抽象类的使用,需要注意的事项:
- 抽象类不能创建对象,如果创建对象,编译无法通过。只能创建其非抽象子类的对象。
- 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
- 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 抽象类的子类,必须重写父类中的所有的抽象方法,否则编译无法通过,除非该子类也是抽象类。
接口
概述
接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是【
封装了方法
】,包含了抽象方法(JDK1.7及以前),默认方法和静态的方法(JDK1.8),私有方法(JDK1.9) 接口的定义,它与类的定义很相似,但是使用interface关键字,他也会被编译生成class文件,但一定要明确他并不是类,而是另外一种引用数据类型。
引用数据类型:类、数组、接口。
接口的使用,不能直接创建对象,但是可以被实现(implements关键字,类似于被继承),一个实现接口的类(可以看做是接口的子类),需要重写接口中的所有的抽象方法,创建该类对象,就可以调用方法了。
接口的定义格式:
public interface 接口名称{ // 抽象方法为主 // 默认方法 // 常量 // 静态方法 // 私有方法(JDK1.9) }
含有抽象方法
抽象方法:使用abstract关键字修饰,没有方法体内容,该方法主要是供子类使用的
public interface InterfaceName{ public abstract }
含有默认方法和静态方法
默认方法:使用default关键字修饰的方法,不可省略,供子类调用或者子类重写。
静态方法:使用static关键字修饰的方法,供接口直接使用。
含有私有方法和私有静态的方法
私有方法:使用private关键字,供接口中的默认方法或者静态方法调用。
代码如下:
public interface InterfaceName{ private void method(){ // 方法体内容。 } }
基本的实现
实现的概述
类与接口的关系,为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为
接口的子类,(实现的动作类似于继承,格式相仿,只是关键字不同,实现使用implements关键字)
非抽象类实现接口:
1.必须重写接口当中的所有的抽象方法
2.继承了接口的当中的默认方法,既可以直接调用,也可以重写
实现格式:
public class 实现类 implements 接口名称{ // 重写接口当中的所有的抽象方法 // 重写接口当中的默认方法 }
抽象方法的使用:
必须全部实现:
代码如下: 定义一个接口:
public interface Biological{// 生物 // 定义一个吃东西的功能 public abstract void eat(); // 定义一个休息的功能 public abstract void sleep(); } // 定义一个实现类 public class Animal implements Biological{ @Override public void eat(){ System.out.println("吃东西"); } @Override public void sleep(){ System.out.println("睡觉"); } } // 定义测试类 public class InterfaceDemo01{ public static void main(String[] args){ // 创建子类对象 Animal ani = new Animal(); // 调用重写之后的方法 ani.eat(); ani.sleep(); } } // 输出结果: // 吃东西 // 睡觉
默认方法的使用
可以继承,可以重写,二选一,但是只能通过实现类的对象来调用
1.继承默认方法,代码如下
public interface Biological{ public default void fly(){ System.out.println("天上飞"); } } // 定义实现类 public class Animal implements Biological{ // 继承 什么也不写,直接调用 } // 定义测试类 public class InterfaceDemo02{ public static void main(String[] args){ // 创建子类对象 Animal ani = new Animal(); // 调用默认方法 ani.fly(); } } // 输出结果:天上飞
2.重写默认方法,代码如下:
public interface Biological{ public default void fly(){ System.out.println("天上飞"); } } // 定义实现类 public class Animal implements Biological{ //重写 @Override public void fly(){ System.out.println("自由自在的飞"); } } public class InterfaceDemo03{ public static void main(String[] args){ // 创建子类对象 Animal ani = new Animal(); // 调用默认方法 ani.fly(); } } // 输出结果:自由自在的飞
静态方法的使用
静态的一般都是和类.class文件相关,只能使用【接口名】来调用,不可以通过实现类的类名或者是实现类的对象来调用。代码如下:
public interface Biological{ public static void run(){ System.out.println("跑起来。。"); } } // 定义实现类 public class Animal implements Biological{ // 无法重写静态方法 } // 定义测试类 public class InterfaceDemo04{ public static void main(String[] args){ // 调用静态方法 Biological.fly(); } } // 输出结果:跑起来
私有方法的使用
私有方法: 只有默认方法可以调用
私有静态方法: 默认方法和静态方法都可以调用
如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,
供默认方法去调用。从设计的角度考虑,私有的方法是对默认的方法和静态的方法的一种辅助。
// 定义一个接口 public interface Biological{ private void run1(){ System.out.println("跑起来。。"); } private default void funMethod01(){ //System.out.println("跑起来。。"); run1(); } private default void funMethod02(){ //System.out.println("跑起来。。"); run1(); } }
接口的多实现
在继承体系中,一个类只能直接继承一个父类,而对于接口来说,一个类可以实现多个接口,这叫做接
口的【多实现】。并且,一个类能直接继承一个父类的同时还可以实现多个接口。
实现格式:
public class ClassName extends 父类 implements 接口名1,接口名2,...{ //重写接口中的所有的抽象方法 //重写接口中的默认方法(可选) //抽象方法重名 }
抽象方法
接口中,有多个抽象方法,实现类必须重写所有的抽象方法,如果抽象方法名有重名的,只需要重写一
次即可,代码如下:
// 定义多个接口 public interface Animal{ public abstract void eat(); public abstract void run(); } public interface Human{ public abstract void eat(); public abstract void run(); } // 继承实现类 public class People implements Animal,Human{ @Override public void eat(){ System.out.println("吃东西!"); } @Override public void run(){ System.out.println("健身。。"); } }
默认方法
接口中,有多个默认方法时,实现类都可继承使用,如果默认方法有重名的,【必须重写一次】代码如下:
public interface A{ public default void methodA(){} public default void method(){} } public interface B{ public default void methodB(){} public default void method(){} } // 定义实现类 public class C implements A,B{ @Override public void method(){ System.out.println("method方法被重写。。。"); } }
静态方法
接口中,如果存在同名的静态方法并不会冲突,原因是只能通过各自的接口名访问静态方法。
优先级的问题
当一个类,既继承了一个父类,又同时实现类多个接口,父类中的成员方法与接口当中的默认方法
重名,子类就近选择父类的成员方法。
代码如下:
public interface A{ public default void methodA(){ System.out.println("AAAAAAAA"); } } // 定义父类 public class D{ public void methodA(){ System.out.println("DDDDDDDD"); } } // 定义子类 public class E extends D implements A{ // 未重写methodA() } // 定义测试类 public class TestInterfaceDemo06{ public static void main(String[] args){ // 创建子类对象E E e = new E(); e.methodA(); } } //输出结果:DDDDDDDD
接口的多继承【了解】
一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用extends关键字,子接口继承父接口的方法,如果父接口中的默认方法有重名方法,那么子接口需要重写一次。代码如下:
public interface A{ public default void method(){ System.out.println("AAAAAAAAAA"); } } public interface B{ public default void method(){ System.out.println("BBBBBBBBBB"); } } // 定义子接口 public interface C extends A,B{ @Override public default void method(){ System.out.println("CCCCCCCCCC"); } }
备注:子接口重写默认方法,default保留。
其他成员特点:
接口中,无法定义成员变量,但是可以定义常量,因为值不可变,默认使用public static final 修饰的
接口中,没有构造方法,不能创建对象
接口当中,没有静态代码块
接口的好处:
设定了规则
降低耦合性【高内聚,低耦合】
扩展原有类的功能
接口与抽象类的区别:
相同点:
- 都包含抽象方法,其子类都必须重写这些抽象方法
- 都不能直接实例化对象
- 都位于继承的顶端,用于被其他类实现或者继承
区别 :
- 抽象类里面可以包含普通成员方法,接口不能包含普通成员方法
- 一个类只能直接继承一个父类(可以是抽象类),一个类也可以实现多个接口
- 类与类之间只能时单继承关系,接口与接口之间可以多继承
- 抽象类可以定义普通的成员变量和常量,接口只能定义常量 public static final 修饰的
-
抽象和接口的区别
2019-05-11 11:28:06在面向对象领域,抽象类主要用来进行类型隐藏。 abstract 关键字只能用于普通方法,不能用于 static 方法或者构造方法中。在抽象类中必须包含至少一个抽象方法,并且所有抽象方法不能有具体的实现,而应在它们的子类...在 Java 中,针对 抽象有两种实现方式 一种是接口,一种是抽象类。很多读者对这两种实现方式比较困惑,到底是使用接口,还是使用抽象类呢?对于它们的选择甚至反映出对问题领域本质的理解,对设计意图的理解是否正确、合理?
在面向对象的设计思想中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有描绘一个具体的对象,那么这样的类就是抽象类,抽象类是对那些看上去不同,但是本质上相同的具体概念的抽象,正是因为抽象的概念在问题领域没有对应的具体概念,所以抽象类是不能够实例化的。
基本语法区别
在 Java 中,接口和抽象类的定义语法是不一样的。这里以动物类为例来说明,其中定义接口的示意代码如下:public interface Animal { //所有动物都会吃 public void eat(); //所有动物都会飞 public void fly(); } 定义抽象类的示意代码如下: public abstract class Animal { //所有动物都会吃 public abstract void eat(); //所有动物都会飞 public void fly(){}; }
可以看到,在接口内只能是功能的定义,而抽象类中则可以包括功能的定义和功能的实现。在接口中,所有的属性肯定是 public、static 和 final,所有的方法都是 abstract,所以可以默认不写上述标识符;在抽象类中,既可以包含抽象的定义,也可以包含具体的实现方法。
在具体的实现类上,接口和抽象类的实 现类定义方式也是不一样的,其中接口实现类的示意代码如下:
public class concreteAnimal implements Animal { //所有动物都会吃 public void eat(){} //所有动物都会飞 public void fly(){} }
抽象类的实现类示意代码如下:
public class concreteAnimal extends Animal { //所有动物都会吃 public void eat(){} //所有动物都会飞 public void fly(){} }
可以看到,在接口的实现类中使用 implements 关键字;而在抽象类的实现类中,则使用 extends 关键字。一个接口的实现类可以实现多个接口,而一个抽象类的实现类则只能实现一个抽象类。
设计思想区别
从前面抽象类的具体实现类的实现方式可以看出,其实在 Java 中,抽象类和具体实现类之间是一种继承关系,也就是说如果釆用抽象类的方式,则父类和子类在概念上应该是相同的。接口却不一样,如果采用接口的方式,则父类和子类在概念上不要求相同。接口只是抽取相互之间没有关系的类的共同特征,而不用关注类之间的关系,它可以使没有层次关系的类具有相同的行为。因此,可以这样说:抽象类是对一组具有相同属性和方法的逻辑上有关系的事物的一种抽象,而接口则是对一组具有相同属性和方法的逻辑上不相关的事物的一种抽象。仍然以前面动物类的设计为例来说明接口和抽象类关于设计思想的区别,该动物类默认所有的动物都具有吃的功能,其中定义接口的示意代码如下:
public interface Animal { //所有动物都会吃 public void eat(); }
定义抽象类的示意代码如下:
public abstract class Animal { //所有动物都会吃 public abstract void eat(); }
不管是实现接口,还是继承抽象类的具体动物,都具有吃的功能,具体的动物类的示意代码如下。
接口实现类的示意代码如下:
public class concreteAnimal implements Animal { //所有动物都会吃 public void eat(){} }
抽象类的实现类示意代码如下:
public class concreteAnimal extends Animal { //所有动物都会吃 public void eat(){} }
当然,具体的动物类不光具有吃的功能,比如有些动物还会飞,而有些动物却会游泳,那么该如何设计这个抽象的动物类呢?可以别在接口和抽象类中增加飞的功能,其中定义接口的示意代码如下:
public interface Animal { //所有动物都会吃 public void eat(); //所有动物都会飞 public void fly(); }
定义抽象类的示意代码如下:
public abstract class Animal { //所有动物都会吃 public abstract void eat(); //所有动物都会飞 public void fly(){}; }
这样一来,不管是接口还是抽象类的实现类,都具有飞的功能,这显然不能满足要求,因为只有一部分动物会飞,而会飞的却不一定是动物,比如飞机也会飞。那该如何设计呢?有很多种方案,比如再设计一个动物的接口类,该接口具有飞的功能,示意代码如下:
public interface AnimaiFly { //所有动物都会飞 public void fly(); }
那些具体的动物类,如果有飞的功能的话,除了实现吃的接口外,再实现飞的接口,示意代码如下:
public class concreteAnimal implements Animal,AnimaiFly { //所有动物都会吃 public void eat(){} //动物会飞 public void fly(); }
那些不需要飞的功能的具体动物类只实现具体吃的功能的接口即可。另外一种解决方案是再设计一个动物的抽象类,该抽象类具有飞的功能,示意代码如下:
public abstract class AnimaiFly { //动物会飞 public void fly(); }
但此时没有办法实现那些既有吃的功能,又有飞的功能的具体动物类。因为在 Java 中具体的实现类只能实现一个抽象类。一个折中的解决办法是,让这个具有飞的功能的抽象类,继承具有吃的功能的抽象类,示意代码如下:
public abstract class AnimaiFly extends Animal { //动物会飞 public void fly(); }
此时,对那些只需要吃的功能的具体动物类来说,继承 Animal 抽象类即可。对那些既有吃的功能又有飞的功能的具体动物类来说,则需要继承 AnimalFly 抽象类。
但此时对客户端有一个问题,那就是不能针对所有的动物类都使用 Animal 抽象类来进行编程,因为 Animal 抽象类不具有飞的功能,这不符合面向对象的设计原则,因此这种解决方案其实是行不通的。
还有另外一种解决方案,即具有吃的功能的抽象动物类用抽象类来实现,而具有飞的功能的类用接口实现;或者具有吃的功能的抽象动物类用接口来实现,而具有飞的功能的类用抽象类实现。
具有吃的功能的抽象动物类用抽象类来实现,示意代码如下:
public abstract class Animal { //所有动物都会吃 public abstract void eat(); }
具有飞的功能的类用接口实现,示意代码如下:
public interface AnimaiFly { //动物会飞 public void fly(); }
既具有吃的功能又具有飞的功能的具体的动物类,则继承 Animal 动物抽象类,实现 AnimalFly 接口,示意代码如下:
public class concreteAnimal extends Animal implements AnimaiFly { //所有动物都会吃 public void eat(){} //动物会飞 public void fly(); }
或者具有吃的功能的抽象动物类用接口来实现,示意代码如下:
public interface Animal { //所有动物都会吃 public abstract void eat(); }
具有飞的功能的类用抽象类实现,示意代码如下:
public abstract class AnimaiFly { //动物会飞 public void fly(){}; }
既具有吃的功能又具有飞的功能的具体的动物类,则实现 Animal 动物类接口,继承 AnimaiFly 抽象类,示意代码如下:
public class concreteAnimal extends AnimaiFly implements Animal { //所有动物都会吃 public void eat(){} //动物会飞 public void fly(); }
这些解决方案有什么不同呢?再回过头来看接口和抽象类的区别:抽象类是对一组具有相同属性和方法的逻辑上有关系的事物的一种抽象,而接口则是对一组具有相同属性和方法的逻辑上不相关的事物的一种抽象,因此抽象类表示的是“is a”关系,接口表示的是“like a”关系。
假设现在要研究的系统只是动物系统,如果设计人员认为对既具有吃的功能又具有飞的功能的具体的动物类来说,它和只具有吃的功能的动物一样,都是动物,是一组逻辑上有关系的事物,因此这里应该使用抽象类来抽象具有吃的功能的动物类,即继承 Animal 动物抽象类,实现 AnimalFly 接口。
如果设计人员认为对既具有吃的功能,又具有飞的功能的具体的动物类来说,它和只具有飞的功能的动物一样,都是动物,是一组逻辑上有关系的事物,因此这里应该使用抽象类来抽象具有飞的功能的动物类,即实现 Animal 动物类接口,继承 AnimaiFly 抽象类。
假设现在要研究的系统不只是动物系统,如果设计人员认为不管是吃的功能,还是飞的功能和动物类没有什么关系,因为飞机也会飞,人也会吃,则这里应该实现两个接口来分别抽象吃的功能和飞的功能,即除实现吃的 Animal 接口外,再实现飞的 AnimalFly 接口。
从上面的分析可以看出,对于接口和抽象类的选择,反映出设计人员看待问题的不同角度,即抽象类用于一组相关的事物,表示的是“isa”的关系,而接口用于一组不相关的事物,表示的是“like a”的关系。
-
抽象类实现某个接口
2021-11-26 10:15:36/** * created by wlx on 2021/11/26 ...抽象类没有实现接口的方法 public abstract class Test implements Itest{ } 子类需实现接口的全部方法,否则报错 public class Testapp extends Test{ @Overri... -
Java 抽象类与接口 编程练习
2021-02-28 18:21:42一、面向抽象编程7175 编程题 编程语言:Java題目內容:使用接口或者抽象类编写程序实现显示员工基本信息。具体要求如下:(1)使用接口或者抽象类实现基类Employer(体会接口和抽象类的不同),包含姓名、部门和工资三个... -
Java 抽象类和接口
2021-11-14 16:09:56接口的特征三、抽象类和接口的区别 一、抽象类 1.抽象类 1.1抽象类的定义 在Java面向对象当中,所有的对象都是用过类进行描绘的,但是并不是所有的类都是用来描绘对象的,如果一个类没有包含足够多的信息来描述一个... -
接口和抽象类(超详细)
2020-09-08 21:49:26首先先来说一下抽象类 要想了解抽象类先看一下抽象方法,抽象方法是一个特殊的方法,他只有声明没有具体的实现。抽象方法用abstract关键字修饰。有抽象方法的类就就是抽象类,抽象类也有abstract关键字修饰。 需要... -
接口:比抽象还抽象
2021-12-13 21:14:11接口(隔离实现),抽象类中既可以定义抽象方法,也可以不定义抽象方法,而接口更加抽象,接口中只能定义抽象方法,在JDK1.8的版本中使用default关键字便可以在接口总实现方法 接口不是具体的类,所以实现接口可以在... -
Java中抽象类和接口的区别
2019-02-07 14:10:07在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类。这两者有太多相似的地方,又有太多不同的地方。很多人在初学的时候会以为它们可以随意互换使用,但是实际则不然。今天我们就一起来学习一下Java中的接口... -
抽象方法和接口的区别
2019-09-11 11:19:08接口和抽象方法的区别: 1、抽象类可以有构造方法,接口中不能有构造方法。 2、抽象类中可以有普通成员变量,接口中没有普通成员变量 3、抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有... -
抽象类和接口有什么区别
2018-08-25 20:36:35不过,面向接口编程的确是一个趋势,java 8 已经支持接口实现默认方法和静态方法了,抽象类和接口之间的差异越来越小。闲话少说,我们开始讨论抽象类和接口的应用。 full_container_taxonomy 上图是 java 容器... -
抽象类和接口的区别
2022-01-25 11:51:361、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。 2、抽象类要被子类继承,接口要被类实现。 3、接口只能做方法申明... -
抽象类和接口的区别及使用场景
2020-01-02 15:49:00在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就可以称之为抽象类。 1.抽象方法:使用... -
接口和抽象类的区别(绝对经典)
2020-08-12 17:40:36抽象类: 构造方法:有构造方法,用于子类实例化使用。 成员变量:可以是变量,也可以是常量。 成员方法:可以是抽象的,也可以是非抽象的。 接口: 构造方法:没有构造方法 成员变量:只能是常量。默认修饰符:... -
抽象类和接口的区别(通俗易理解)
2022-07-08 10:29:14抽象类和接口的区别,从概念,特点及意义三个方面进行介绍 -
接口中的抽象方法
2021-07-11 11:42:59接口中所有方法都是抽象方法,无论你加不加abstract。所有实现指定接口的类都必须重写并实现该接口的所有方法,否则这个类就是抽象类。 -
Java 抽象类和接口的区别
2022-03-15 20:06:50抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract (隐式声明)方法; 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final(隐式声明)类型的(必须在声明时... -
java抽象类和接口有什么意义
2021-02-04 16:53:06为什么接口和抽象类不能实例化,为什么接口可以多个实现而抽象类只能单继承,特别是java8之后,抽象类和接口里面都可以写代码后,就更加分不清了,今天重新整理一下。 什么是抽象类(abstract class) 使用abstract... -
Java中的接口与抽象方法
2021-03-06 22:33:03Java中的接口与抽象方法时间:2017-06-27来源:华清远见JAVA学院今天华清Java学院小编来和大家分享一下Java中接口和抽象方法的一些知识。Java中接口是什么?什么是Java接口呢?接口在java中是一个特殊的类,不过再... -
面试:一文搞懂抽象类和接口的区别
2020-08-03 19:24:00接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念,接口在JAVA编程语言中是一个抽象类型,是抽象方法的集合。类描述对象的属性和方法。接口则包含类要实现的方法。 那么我们就来完整的写一个接口:... -
接口和接口实现类,接口与抽象类
2019-02-07 16:34:56Java不支持多重继承,即一个...接口体包括属性常量和抽象方法。 [public] interface 接口名 { 属性常量 ... 抽象方法 ... } interface是声明一个接口的关键字,在Java中,接口的属性只允许为静态... -
抽象类和接口的区别(什么时候用抽象类,什么时候用接口?)
2020-12-12 14:45:26如果在你的程序中有下面的这些情况,那你就要考虑使用抽象类了: 你想要在几个关联紧密的类之间共享代码。 你想要继承抽象类的那些类有一些公共方法或属性抑或是有修改protected或private属性的权限。这时你也... -
Java中抽象类实现接口
2021-05-06 14:22:31抽象类 Java中的抽象类主要是作为一个公共父类的作用,它可以抽象出用来描述一种类型应该具备的基本特征与功能,具体行为则由子类通过方法重写来完成。 抽象类具有的性质 类定义前需要加上abstract关键字 抽象类中... -
java抽象类和接口
2019-05-14 17:34:15java抽象类和接口 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 开发工具与关键技术:MyEclipse10 作者:朱海恩 撰写时间: 2019.04.30 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~... -
抽象类、抽象方法和接口的区别和联系
2019-07-20 20:23:29抽象类,抽象方法和接口是java基础里面比较重要但是容易混淆的知识点,在实际运用的时候因为具有很多共同点所以也会有时候也会不知道用什么或者用错,正好借这个机会整理一下这方面的知识~~_~ 抽象类和抽象... -
第四章 抽象类与接口
2020-04-11 21:02:46抽象类与接口区别1、结构2、继承方式3、构造方法4、多/单继承5、速度6、设计举例四.父类的静态方法能不能被子类重写1、重写/重载2、静态方法3、父类的静态方法能不能被子类重写? abstract class和interface是Java... -
接口能否继承接口?抽象类能否实现接口?抽象类能否继承具体类?抽象类中能否有静态的main方法?
2020-12-02 13:38:45抽象类并不能继承接口,但可以实现接口。 抽象类可以继承具体类,前提是具体类必须具有构造函数且具有访问权限。这里需要说明,当一个具体类没有写构造函数时,系统会自动生成默认的无参构造器,意味着没有写构造...