关于私有成员访问的JDK 7中的javac行为更改

时间:2012-08-20 19:25:42

标签: java javac java-7 private-members

此代码使用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发行说明中提到这样的更改。有人提到有关泛型类型参数的私有成员的访问权限更改,但这不适用于此。

这是javac的回归吗?它现在是否执行了以前没有强制执行的限制?

1 个答案:

答案 0 :(得分:7)

好吧,我对此感到困惑,我能冒险的唯一解释就是两件事的结合。

1_ getClass() docs说出以下内容:

  

实际结果类型为Class<? extends |X|>,其中|X|为   擦除getClass所在表达式的静态类型   调用。

2_其中一个incompatibilities introduced in Java 7 编译器不再允许访问类型变量的私有成员

因此,编译器不确定是否对基类或子类进行了转换,并且它阻止访问私有成员,因为如果将转换分配给子类,即使在原始中定义,它也是非法的父类,如以下示例所示:

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怪癖的另一个原因,因为规则在更复杂的例子中更有意义。