传统上,Java程序的接口是将相关方法按照约定组合到一起的方式。实现接口的类必须为接口中定义的每个方法提供一个实现,或者从父类中继承它的实现。但是,一旦类库的设计者需要更新接口,向其中加入新的方法,这种方式就会出现问题。例如,给List接口加一个方法,那么所有实现类都需要实现这个方法。
JAVA8为了解决这个问题,引入新的机制,支持在声明方法的同时提供方法。JAVA8允许在接口内声明静态方法。
实现接口的类,如果不显式地提供该方法的具体实现,就会自动继承默认的实现。
List<Integer> numbers = Arrays.asList(3, 5, 1, 2, 6);
numbers.sort(Comparator.naturalOrder());
我们调用了 Comparator.naturalOrder方法。这是Comparator接口的一个全新的静态方法,它返回一个 Comparator对象,并按自然序列对其中的元素进行排序。
Collection中的stream方法定义,它也是Collection接口的一个默认方法。
回顾spliterator,需要实现一个遍历元素的方法,
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
默认方法的引入就是为了以兼容的方式解决像 Java API这样的类库的演进问题的。
JAVA8中的抽象类和抽象接口
一个类只能继承一个抽象类,但是一个类可以实现多个接口。
一个抽象类可以通过实例变量(字段) 一个通用 ,而接口是不能有实例变量的。
默认方法的使用模式
可选方法
Iterator接口定义了hasNext、next,还定义了remove方法。Java 8 之前,由于用户通常不会使用该方法,remove方法常被忽略。因此,实现Interator接口的类通常会为remove方法放一个空的实现,这些都是些无用处的模板代码。
采用默认方法之后,你可以为这种类型的方法提供一个默认的实现,这样实体类就无需在自己的实现中显式地提供一个空方法。
行为的多继承
一个类可以有多个接口,由于Java 8中接口方法可以包含实现,类可以从多个接口中继承它们的行为。
解决冲突规则
Java语言中一个类只能继承一个类,但是一个类可以实现多个接口。随着默认方法在Java 8中引入,有可能出现一个类继承了多个方法而它们使用的却是同样的函数签名。这种情况下,类会选择使用哪一个函数?
三个原则
- 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
- 如果无法依据第一条进行判断,那么子接口的优先级更高。函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
- 如果还是无法判断,继承了多个接口的类必须通过显示覆盖和调用期望的方法,显示的选择哪一个默认方法的实现。
public interface A {
default void hello() {
System.out.println("Hello from A");
}
}
public interface B extends A {
default void hello() {
System.out.println("Hello from B");
} }
public class C implements B, A {
public static void main(String... args) {
new C().hello();//根据规则2,会打印B接口的默认方法Hello from B
}
}
public class D implements A{ }
public class C extends D implements B, A {
public static void main(String... args) {
new C().hello();//会打印Hello from B。 因为A中父类没有具体方法,而是实现了接口A。但B更具体(我理解更接近吧)。
}
}
public class D implements A{
void hello(){
System.out.println("Hello from D");
}
}
public class C extends D implements B, A {
public static void main(String... args) {
new C().hello();//会打印HELLO FROM D
}
}
显示消除歧义
java 8中引入了一种新的语法X.super.m(…),其中X是你希望调用的m方法所在的父接口。
public interface A{
default void hello(){
System.out.println("Hello from A");
}
}
public interface B extends A { }
public interface C extends A { }
public class D implements B, C {
public static void main(String... args) {
new D().hello();//会打印Hello from A
}
}
如果B中实现了hello方法,那么会打印B中实现的方法。
Java 8中的接口可以通过默认方法和静态方法提供方法的代码实现。
默认方法的开头以关键字default修 ,方法体与常规的类方法相同。