Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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:

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.

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. 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? Is it now enforcing a restriction that it wasn't enforcing before?

like image 990
Phil Shapiro Avatar asked Aug 20 '12 19:08

Phil Shapiro


People also ask

Which commands compiles a Java program in which the class is defined as Hello?

To run the program (again using the Java SDK) type: % java Hello. This command should produce the output: Hello World! The java command is the Java interpreter; it runs the Java Virtual Machine. You pass java the name of the class that you want to run.

What is javac compiler in Java?

DESCRIPTION. The javac tool reads class and interface definitions, written in the Java programming language, and compiles them into bytecode class files. It can also process annotations in Java source files and classes.

Which options are commonly used when compiling a module?

In order compile all Java source files in a given module, we actually need 3 options: "--module <module-name>": Specify which module to compile. "-d <directory>": Specify where to place generated class files. "--module-source-path <path-list>": Specify where to find input source files of required modules.

Where is Java compiler located?

The value that you want to add is most likely C:\Program Files\Java\jdk-14.0. 2\bin if you are installing "JDK 14.0. 2". This is the location where the Java compiler ('java.exe') was installed in your file system.


1 Answers

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:

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_ One of the incompatibilities introduced in Java 7 is Compiler No Longer Allows Access to Private Members of Type Variables.

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.

like image 131
madth3 Avatar answered Oct 27 '22 04:10

madth3