此代码使用 javac JDK 版本 1.6.0_33-b03-424 编译正常,但使用 javac JDK 版本 1.7.0_06 无法编译。
public class Test {
private final int i = 0;
void test(Object o) {
if (getClass().isInstance(o)) {
System.out.println(getClass().cast(o).i);
}
}
}
javac 输出是:
Test.java:6: error: i in Test is defined in an inaccessible class or interface
System.out.println(getClass().cast(o).i);
^
1 error
更改代码以将 getClass.cast()
的结果存储在一个临时变量中允许程序无错编译。
这很容易变通,但我找不到 JLS 7 中此更改的任何理由,也找不到 JDK 7 发行说明中任何此类更改的提及。提到了将类型参数的私有(private)成员更改为泛型的访问权限更改,但这在此处不适用。
这是 javac 的回归吗?它现在是否正在执行以前未执行的限制?
最佳答案
好吧,我对此感到困惑,我可以冒险的唯一解释是两件事的结合。
1_ getClass()
docs说以下内容:
The actual result type is
Class<? extends |X|>
where|X|
is the erasure of the static type of the expression on whichgetClass
is called.
2_ incompatibilities introduced in Java 7 之一编译器不再允许访问类型变量的私有(private)成员。
因此,编译器不确定是对基类还是子类进行了强制转换,它会阻止访问私有(private)成员,因为如果将强制转换分配给子类,即使在原始类中定义了它也是非法的父类,如下例所示:
class BaseTest {
private final int i = 1;
void test(Object o) {
if (getClass().isInstance(o)) {
TestAccess to = TestAccess.class.cast(o);
//System.out.println(to.i); // ERROR: i has private access in BaseTest
}
}
}
class TestAccess extends BaseTest{}
因此,我猜这是 Java 的又一个怪癖,因为规则在更复杂的示例中更有意义。
关于JDK 7 中有关私有(private)成员访问的 javac 行为更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12043831/