jdk1.8_默认方法

默认方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface List<E> extends Collection<E> {
...
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
...
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
...
...
}

接口类中支持申明带有实现的方法,可以由接口实现类的实例调用

和抽象类的区别

  • 一个类只能继承一个抽象类;但是一个类可以实现多个接口。
  • 抽象类有实例变量,而接口只能有类变量

多继承多实现中的优先级

由于一个类可以实现多个接口,所以当一个类继承了多个签名相同的方法,类在选择方法时的优先级规则:

  • 类中的方法优先级最高,类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
  • 如果第一条无法判断,那么子接口的优先级更高:方法签名相同时,优先选择拥有最具体实现的默认方法的接口, 即如果B继承了A,那么B就比A更加具体。
  • 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法, 显式地选择使用哪一个默认方法的实现。

场景1:

1
2
3
4
5
public interface A {
default void hello() {
System.out.println("hello from A");
}
}
1
2
3
4
5
public interface B extends A {
default void hello() {
System.out.println("hello from B");
}
}
1
2
3
4
5
public class C implements A, B {
public static void main(String[] args) {
new C().hello();//hello from B
}
}

类中无方法,B继承了A,故认为B中的hello()更具体,输出“hello from B”

场景2:

若C继承了A的实现类D

1
2
3
public class D implements A {

}
1
2
3
4
5
public class C extends D implements A, B {
public static void main(String[] args) {
new C().hello();//hello from B
}
}

C继承了D,但D没有对A的默认方法进行重写,故比较AB,还是输出“hello from B”

场景3:

若D中覆盖了A的默认方法

1
2
3
4
5
public class D implements A {
public void hello() {
System.out.println("hello from D");
}
}

父类中方法具有更高优先级,打印“hello from D”

场景4:

若B不再继承A

1
2
3
4
5
public interface A {
default void hello() {
System.out.println("hello from A");
}
}
1
2
3
4
5
public interface B {
default void hello() {
System.out.println("hello from B");
}
}
1
2
3
4
5
public class C implements A, B {
public static void main(String[] args) {
new C().hello();
}
}

由于编译器无法识别A还是B的实现更加具体,所以会抛出编译错误:“C inherits unrelated defaults for hello() from types A and B”。
解决冲突,可以在C中覆盖hello()方法并在方法内显示的选择调用A还是B的方法

1
2
3
4
5
6
7
8
9
10
11
public class C extends D implements A, B {
public void hello() {
// 显式地选择调用接口B中的方法
// 同理,要调用接口A中的方法,可以这样:A.super.hello()
B.super.hello();
}

public static void main(String[] args) {
new C().hello();//hello from B
}
}
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020 李明华
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信