考虑以下Java程序:
public class IntersectionBug {
public static interface FooInterface {
public void foo();
}
public static class FooSupport {
protected void foo() {
}
}
public static class Whatever<T extends FooSupport & FooInterface> {
}
}
在JDK 1.8编译器下无法编译:
$ javac IntersectionBug.java
IntersectionBug.java:12: error: foo() in FooSupport cannot implement foo() in FooInterface
public static class Whatever<T extends FooSupport & FooInterface> {
^
attempting to assign weaker access privileges; was public
1 error
很明显,如果某个类型T
既是FooSupport
也是FooInterface
,则它必须具有public void foo()
,因此错误是虚假的。
我的问题:这是编译器错误,还是JLS确实指定该程序无效?如果是后者,为什么这里的次优JLS行为呢?
答案 0 :(得分:0)
JLS §4.9通过名义类的概念定义了路口类型及其成员。在您的特定情况下,概念类为:
class <notional> extends FooSupport implements FooInterface {}
请注意空的班级正文。
JLS段落旨在暗示概念类必须格式正确,否则会发生编译错误。显然,为公共接口方法继承受保护的实现的类的格式不正确。
我同意,还有 种其他方式可以指定允许使用FooSupport未知子类的交集类型,该子类可以通过以公共可见性覆盖该方法来解决上述冲突。
我相信选择通过概念类进行定义的样式是为了避免复杂性。看看§4.9与其他定义相比有多简洁。
PS:ecj也拒绝您的示例,说:
继承的方法IntersectionBug.FooSupport.foo()无法在IntersectionBug.FooInterface中隐藏公共抽象方法