Javac 在交集类型上失败并显示 "attempting to assign weaker access privileges"
Javac fails with "attempting to assign weaker access privileges" on intersection type
考虑这个 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 行为不是最理想的?
JLS §4.9 通过 名义 class 的概念定义交叉点类型及其成员。在您的特定情况下,名义上的 class 是:
class <notional> extends FooSupport implements FooInterface {}
请注意空 class 正文。
JLS 段落意在暗示名义上的 class 必须格式正确,否则会出现编译错误。显然,继承 public 接口方法的受保护实现的 class 格式不正确。
我同意 可能 有其他方法可以指定交集类型,允许 FooSupport 的未知子 classes 通过覆盖具有 public 可见性的方法。
我相信选择概念性 class 的定义风格是为了避免复杂性。看看 §4.9 与其他定义相比有多简洁。
PS: ecj 也拒绝了你的例子,说:
The inherited method IntersectionBug.FooSupport.foo() cannot hide the public abstract method in IntersectionBug.FooInterface
考虑这个 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 行为不是最理想的?
JLS §4.9 通过 名义 class 的概念定义交叉点类型及其成员。在您的特定情况下,名义上的 class 是:
class <notional> extends FooSupport implements FooInterface {}
请注意空 class 正文。
JLS 段落意在暗示名义上的 class 必须格式正确,否则会出现编译错误。显然,继承 public 接口方法的受保护实现的 class 格式不正确。
我同意 可能 有其他方法可以指定交集类型,允许 FooSupport 的未知子 classes 通过覆盖具有 public 可见性的方法。
我相信选择概念性 class 的定义风格是为了避免复杂性。看看 §4.9 与其他定义相比有多简洁。
PS: ecj 也拒绝了你的例子,说:
The inherited method IntersectionBug.FooSupport.foo() cannot hide the public abstract method in IntersectionBug.FooInterface