# 抽象类 VS 接口

关注对象的本质时用抽象类,关注一个对象的功能时用接口。(抽象类是关注类的属性,接口是关注类的行为)

举例:飞机和鸟,飞机的各个类型和鸟的各个类型需要通过分别继承飞机和鸟实现,而他们的公共特点飞行,是他们共同的行为,需要定义为接口,使得他们均能够实现。

# 抽象类

  1. 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
  6. abstract不能与final并列修饰同一个类,因为抽象类是要被继承的(同4)。
  7. abstract不能与privatestaticfinalnative并列修饰同一个方法,因为抽象方法需要在子类中被具体实现(同5)。

# 接口

  1. 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstractJAVA8的新特性:接口声明可以包含defaultstatic
  2. 接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量(并且只能是public,用private修饰会报编译错误)。
  3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

# 抽象类和接口的区别

请注意JAVA8JAVA7版本之间的区别

  1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。
  3. 接口中不能含有静态代码块以及静态方法(用static修饰的方法),而抽象类是可以有静态代码块和静态方法。
  4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口

# 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

在上面的 Math 接口中,我们添加了一个与实际方法体相乘的方法。

# 为什么我们需要默认方法?

为什么要在接口中添加方法?我们会这样做是因为接口与其实现类耦合得太紧密了。即不可能在不破坏实现类的情况下在接口中添加方法。一旦你在接口中添加了一个方法,它的所有实现类都必须声明这个新方法的方法体。

Java 8 开始,事情开始变得丑陋。引入了一个很酷的新功能Lambda。但是,无法在现有 Java 库(例如 java.util 包)中使用此功能。如果你在 interface 中添加一个方法List,它会破坏一切。 您需要在每个实现List接口的类中添加它的实现。想象一下在现实世界中有多少自定义类会发生变化。

所以为了向后兼容Java 8 巧妙地添加了Default Methods

Last Updated: 3 years ago