# 抽象类 VS 接口
关注对象的本质时用抽象类,关注一个对象的功能时用接口。(抽象类是关注类的属性,接口是关注类的行为)
举例:飞机和鸟,飞机的各个类型和鸟的各个类型需要通过分别继承飞机和鸟实现,而他们的公共特点飞行,是他们共同的行为,需要定义为接口,使得他们均能够实现。
# 抽象类
- 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
- 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
- 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
- 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
abstract
不能与final
并列修饰同一个类,因为抽象类是要被继承的(同4)。abstract
不能与private
、static
、final
或native
并列修饰同一个方法,因为抽象方法需要在子类中被具体实现(同5)。
# 接口
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为
public abstract
(JAVA8
的新特性:接口声明可以包含default
、static
) - 接口中可以含有变量,但是接口中的变量会被隐式的指定为
public static final
变量(并且只能是public
,用private
修饰会报编译错误)。 - 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
# 抽象类和接口的区别
请注意
JAVA8
与JAVA7
版本之间的区别
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,
但是接口中的方法不行。 - 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是
public static final
类型的。 接口中不能含有静态代码块以及静态方法(用,而抽象类是可以有静态代码块和静态方法。static
修饰的方法)- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
# Java 8 引入了新的语言特性——默认方法(Default Methods)
public interface Math {
int add(int a, int b);
default int multiply(int a, int b) {
return a * b;
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
在上面的 Math 接口中,我们添加了一个与实际方法体相乘的方法。
# 为什么我们需要默认方法?
为什么要在接口中添加方法?我们会这样做是因为接口与其实现类耦合得太紧密了。即不可能在不破坏实现类的情况下在接口中添加方法。一旦你在接口中添加了一个方法,它的所有实现类都必须声明这个新方法的方法体。
从 Java 8
开始,事情开始变得丑陋。引入了一个很酷的新功能Lambda
。但是,无法在现有 Java
库(例如 java.util
包)中使用此功能。如果你在 interface
中添加一个方法List
,它会破坏一切。
您需要在每个实现List接口的类中添加它的实现。想象一下在现实世界中有多少自定义类会发生变化。
所以为了向后兼容,Java 8
巧妙地添加了Default Methods
。
← Reference 引用 HashMap →