我有四个类,看起来像这样:
public interface Foo<T> {
...
default boolean isEmpty() {
return false; //dummy value real implementation is not relevant for the problem
}
}
public interface CharSequence { //java.lang.CharSequence
...
default boolean isEmpty() {
return true; //dummy value real implementation is not relevant for the problem
}
public abstract class Bar<T> implements Foo<T> {
...
}
public final BarImpl extends Bar<Character> implements CharSequence { //typical diamond problem
...
@Override
public boolean isEmpty() { //needed to resolve diamond problem
return Foo.super.isEmpty() // Compile Error: No enclosing instance of the type Foo<T> is accessible in scope
return Bar.super.isEmpty() // Compile Error: No enclosing instance of the type Bar<T> is accessible in scope
return CharSequence.super.isEmpty() // compiles
}
为什么我不能访问来自扩展栏的默认实现?
BarImpl
不能显式调用Foo
的default
方法,因为BarImpl
没有直接实现Foo
。它扩展了直接实现Foo
的Bar
,因此,是否覆盖Foo
的default
方法由Bar
决定。
BarImpl
只能通过super.isEmpty()
调用Bar
的isEmpty()
方法,如果Bar
决定不重写Foo
的default
方法,则可能最终调用Bar
的具体方法。
注意T.super.method()
只能在T
是直接实现的超接口(即没有被超类或其他超接口实现)或T
是内部类的封闭类型时使用。第二个用例是">在范围内没有…的封闭实例可访问"错误消息的原因。
import java.util.Objects;
class Test {
public static void main(String... arg) {
System.out.println(new BarImpl().isEmpty());
}
}
public interface Foo<T> {
default boolean isEmpty() {
System.out.println(" Foo's default method");
return false;
}
}
public abstract class Bar<T> implements Foo<T> {
}
public final class BarImpl extends Bar<Character> implements CharSequence {
@Override
public boolean isEmpty() {
System.out.println("calling (Bar) super.isEmpty();");
super.isEmpty();
System.out.println("calling CharSequence.super.isEmpty();");
return CharSequence.super.isEmpty();
}
public char charAt(int index) {
Objects.checkIndex(index, length());
return (char)('A' + index);
}
public int length() {
System.out.println(" length() [CharSequence's default method]");
return 26;
}
public CharSequence subSequence(int start, int end) {
Objects.checkFromToIndex(start, end, length());
return new StringBuilder(end - start).append(this, start, end);
}
public String toString() {
return new StringBuilder(length()).append(this, 0, length()).toString();
}
}
calling (Bar) super.isEmpty();
Foo's default method
calling CharSequence.super.isEmpty();
length() [CharSequence's default method]
false