Details
-
Bug
-
Resolution: Fixed
-
P4
-
8
Description
Tentatively considering this a spec bug, since the inconsistency is very old, and there's no particular reason javac's approach is worse than JLS's (in fact, in some ways it is nicer). (Eclipse behavior matches javac.)
6.6.2 claims that a protected method is inaccessible if 1) the invocation is in a different package, and either 2) the invocation is not from a subclass of the declaring class, or 3) the invocation has an expression-/variable-qualified form and the qualifying type is not a subclass of the invoking class.
Javac implements #3 differently: the method is inaccessible if it is not declared static and the qualifying type is not a subclass of the invoking class. The syntactic form of the invocation is irrelevant.
To illustrate:
package p1;
public class A {
protected void m(String s) { System.out.println("instance"); }
protected static void m(Object o) { System.out.println("static"); }
}
package p2;
public class B extends p1.A {}
package p2;
public class C extends p1.A {
public static void main(String... args) {
test(new p1.A(), new B(), new C());
}
public static void test(p1.A a, B b, C c) {
p1.A.m("x"); // *** JLS: error, malformed instance invocation; javac: print "static" ***
B.m("x"); // *** JLS: error, malformed instance invocation; javac: print "static" ***
C.m("x"); // JLS: error, malformed instance invocation; javac: error invoking instance
a.m("x"); // *** JLS: error, no accessible methods; javac: print "static" ***
b.m("x"); // *** JLS: error, no accessible methods; javac: print "static" ***
c.m("x"); // JLS: print "instance"; javac: print "instance"
}
}
JLS text is essentially the same since the 1st edition.
javac behavior is the same in 6, 7, and 8.
ecj behavior is the same in 3.5, 3.6, 3.7, 3.8, and 3.9.
6.6.2 claims that a protected method is inaccessible if 1) the invocation is in a different package, and either 2) the invocation is not from a subclass of the declaring class, or 3) the invocation has an expression-/variable-qualified form and the qualifying type is not a subclass of the invoking class.
Javac implements #3 differently: the method is inaccessible if it is not declared static and the qualifying type is not a subclass of the invoking class. The syntactic form of the invocation is irrelevant.
To illustrate:
package p1;
public class A {
protected void m(String s) { System.out.println("instance"); }
protected static void m(Object o) { System.out.println("static"); }
}
package p2;
public class B extends p1.A {}
package p2;
public class C extends p1.A {
public static void main(String... args) {
test(new p1.A(), new B(), new C());
}
public static void test(p1.A a, B b, C c) {
p1.A.m("x"); // *** JLS: error, malformed instance invocation; javac: print "static" ***
B.m("x"); // *** JLS: error, malformed instance invocation; javac: print "static" ***
C.m("x"); // JLS: error, malformed instance invocation; javac: error invoking instance
a.m("x"); // *** JLS: error, no accessible methods; javac: print "static" ***
b.m("x"); // *** JLS: error, no accessible methods; javac: print "static" ***
c.m("x"); // JLS: print "instance"; javac: print "instance"
}
}
JLS text is essentially the same since the 1st edition.
javac behavior is the same in 6, 7, and 8.
ecj behavior is the same in 3.5, 3.6, 3.7, 3.8, and 3.9.
Attachments
Issue Links
- relates to
-
JDK-8032830 6.6.2: Handle method references in protected access rules
-
- Closed
-
-
JDK-8033466 15.12.4.3: Clean up description of protected access
-
- Closed
-