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

标签 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 发行说明中任何此类更改的提及。提到了将类型参数的私有(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 which getClass 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/

相关文章:

java - Android Studio 卡在加载屏幕上

intellij-idea - Java 7 和 IntelliJ

java - 使用java获取XML的某些值

java - Spring 网络套接字 : message not published

java检查对象列表是否包含具有具体名称的对象

eclipse - 使用 javac 编译 OSGI 4.2 应用程序时,编译器看不到泛型信息

java - 以 Java 6 为目标并使用 JDK 7 编译器时如何抑制引导类路径警告

Java:数据结构和通配符的泛型

Javac 未与 openjdk-6-jdk 一起安装

java - 如何选择以编程方式运行哪个 JDK