简体   繁体   English

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

[英]javac behavior change in JDK 7 regarding private member access

This code compiles OK using javac JDK version 1.6.0_33-b03-424, but doesn't compile using javac JDK version 1.7.0_06. 此代码使用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 output is: 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

Changing the code to store the result of getClass.cast() in a temporary variable allows the program to compile without error. 更改代码以将getClass.cast()的结果存储在临时变量中允许程序无错误地编译。

This is easy to work around, but I can't find any rationale for this change in the JLS 7, or any mention of a change like this in the JDK 7 release notes. 这很容易解决,但我找不到JLS 7中这种更改的任何理由,或者在JDK 7发行说明中提到这样的更改。 There is a mention of an access change regarding private members of type parameters to a generic, but that doesn't apply here. 提及有关泛型的类型参数的私有成员的访问更改,但这不适用于此处。

Is this a regression in javac? 这是javac的回归吗? Is it now enforcing a restriction that it wasn't enforcing before? 它现在是否执行了以前没有强制执行的限制?

Well, I'm puzzled by this and the only explanation I can adventure is the conjunction of two things. 好吧,我对此感到困惑,我能冒险的唯一解释就是两件事的结合。

1_ getClass() docs say the following: 1_ getClass() docs说如下:

The actual result type is Class<? extends |X|> 实际的结果类型是Class<? extends |X|> Class<? extends |X|> where |X| Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. 是调用getClass的表达式的静态类型的擦除。

2_ One of the incompatibilities introduced in Java 7 is Compiler No Longer Allows Access to Private Members of Type Variables . 2_ Java 7中引入的一个不兼容性编译器不再允许访问类型变量的私有成员

So, the compiler is unsure it the cast is made to the base class or a subclass and it blocks accesing a private member, since if the cast were to be assigned to a subclass it would be illegal even if defined in the original parent class, as shown in the following example: 因此,编译器不确定是否对基类或子类进行了转换,并且它阻止访问私有成员,因为如果将转换分配给子类,即使在原始父类中定义,它也是非法的,如以下示例所示:

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{}

So, I guess it's one more of Java quirks due to rules that make more sense in more complex examples. 因此,我认为这是Java怪癖之一,因为规则在更复杂的例子中更有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM