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

2022-09-04 04:19:25

此代码使用 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

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

1_ getClass() 文档是这样说的:

实际结果类型是 where 是擦除所调用的表达式的静态类型。Class<? extends |X|>|X|getClass

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


答案 2