抽象类
用abstract修饰的方法叫抽象方法。用abstract关键字修饰的类,叫抽象类。
抽象方法:只有方法的声明,没有方法的实现,以分号结束。比如:public abstract void talk();
抽象类定义:
类的修饰符 abstract class 类名有抽象方法的类必须定义为抽象类。存在意义:实现程序的多态性。(必须被继承,否则它的存在是没有意义的) 可以看看我这篇文章了解多态Java之封装、继承和多态(超详细) - 掘金 (juejin.cn)
抽象类的特点
a、抽象类不能被实例化,只能被继承;
b、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;
c、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;
d、一个子类继承一个抽象类,则子类必须实现父类抽象方法,否则子类也必须定义为抽象类;
e、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。
解决疑问点:
问题:既然普通方法可以被重写,那么子类中有不同执行步骤我再重写就好了,为什么我还需要抽象方法呢?
答:抽象方法是必须被重写且父类中没有方法体,而普通方法不是必须被重写而且父类中有方法体;这样就造成一个问题:程序过大而不使用这种方法,父类中普通方法太多,子类都要记得去重写,但是java虚拟机又不会告诉你去重写,不重写子类就按照父类默认的方法体执行了;而抽象方法就不同了,子类不重写java虚拟机报错,这时候就起到了提醒以及强制的作用。
接口
Java中接口使用interface关键字修饰。 定义:接口的存在是为了实现程序的可扩展性。
存在意义:如果某一个类要扩充功能怎么办?那么我们就要去修改这个类的父类甚至说是超类吗?这显然不合理。(而且如果你使用别人提供的类,根本就不可能去修改它)。你想给某个类扩展功能,只需要给这个类实现一个新的接口就行。
接口的特点
a、接口可以包含变量、方法;变量被隐式地指定为public static final,方法被隐式地指定为public abstract;
b、接口里的变量称为全局常量,只能显式赋值。比如int MAX_SPEED=100;
c、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题;
d、接口不能直接被实例化,需要一个类来实现它;
e、一个类可以实现多个接口,但是类只能继承一个类;
f、JDK1.8中对接口增加了新的特性:(1)默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法只能被实现子类的对象调用,不能被重写;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;(2)静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。
代码举例:(判断一下是否编译错误,如果没有的话,输出啥)
public class BeanUtilsTest {
public static void main(String[] args) {
new C().print();
}
}
interface A{
int x=1;
void a();
default void sayHello(){
System.out.println("Hello World");
}
}
class B{
int x=0;
public void a(){
System.out.println("你好");
}
}
class C extends B implements A{
public void print(){
sayHello();
System.out.println(A.x);
System.out.println(super.x);
}
}
答案是:
Hello World
1
0
当然不会编译报错啦,虽然C类没有重写接口A的a方法,但是继承了B类的a方法。试想一下,如果C类的print方法里直接输出x会不会报错。
注:当一个类继承了一个父类,又实现了多个接口,父类中的成员方法与接口中的默认方法重名,那么子类就近选择执行父类的成员方法。
抽象类与接口的区别
抽象级别(从高到低):接口>抽象类>实现类。
接口是对动作的抽象,表达的是 like a 的关系;抽象类是对根源的抽象,表达的是 is a 的关系。
我们从设计目的来区分抽象类和接口:
接口的设计目的是“协作”与“解耦合”。接口只定义声明,而不定义内容,这因为在程序中“声明”就已经确定了方法的功能和如何调用这些问题,这样功能的使用者和实现者互相可以不用了解对方的实现就可以协作。接口其实是一套规约,定义职责划分和交互方式这些内容,这些东西确定功能的使用者和提供者之间怎么协作。这种规约有时都不必是代码,比如HTTP接口往往就是以文档的形式存在。
而抽象类的设计目的,是代码复用。当不同的类具有某些相同的行为(记为行为集合A),且其中一部分行为的实现方式一致时(A的非真子集,记为B),可以让这些类都派生于一个抽象类。在这个抽象类中实现了B,避免让所有的子类来实现B,这就达到了代码复用的目的。而A减B的部分,留给各个子类自己实现。正是因为A-B在这里没有实现,所以抽象类不允许实例化出来。
注意:接口强调特定功能的实现,而抽象类强调所属关系。
应用场景总结
抽象类的应用场景一般用于抽取不同事物的共有特性,然后可以用接口实现不同事物的不同行为。遇到需求,先分析不同的对象是否有共同点,比如门,都可以开和关,这个就可以抽取出来定义一个抽象类,而有的门有门铃可以摁,有的门没有,那就将有门铃的对象实现摁门铃这个动作的接口。