Community
Participate
Working Groups
Let's consider an example: package junit.jxelink.devirtualization; public class BT_Method { protected int return0() { return -1; } } package junit.jxelink.devirtualization.addon; public class ScMethod extends BT_Method { protected int return0() { return 0; } } package junit.jxelink.devirtualization; public class BT_Class { public int return0() { return new ScMethod().return0(); } } When one puts the cursor on "return0()" method invocation in BT_Class and presses F3 the decalaration is resolved as BT_Method.return0, which is wrong. Apparently JDT thinks that ScMethod.return0 isn't accessible, but it is, according to Java Lang Spec ver.2; section 6.6.2.1 "Access to a protected Member"
I tried the following example: package a; public class A { protected int return0() { return -1; } } package a.b; public class B extends a.A { protected int return0() { return 0; } } package a; import a.b.B; public class C { public static void main(String[] args) { System.out.println(new B().return0()); } } I compiled with javac and ran a.C.main()... the result is 0 as expected. But if you rename A.return0() to return1() then a.C fails to compile because: a/C.java:5: return0() has protected access in a.b.B System.out.println(new B().return0()); Our understanding (backed up by all the test suites) is that protected fields/methods are not visible at compile time outside their package unless the type is a subclass. Radek: Do you agree?
I'm not sure whether I can agree. As you can see in your example protected method a.b.B.return0() IS visible from a.C, but the method is neither in the same package as C nor C is "subclass related" to B. And in this case, unlike Java lang spec, Java VM spec is very clear on this: the method is visible. That came to me as surprise as well. My point is: pressing F3 on the invocation of a.b.B.return0() from a.C.main should lead to the correct method, not a.A.return0() as it does now.
Sorry I guess I wasn't clear enough... the protected method B.return0() is not visible at compile time (as you can see when A.return0() does not exist) but is visible to the VM at execution time if it overrides a visible method (A.return0 ()). F3 shows the method that the compiler found, not the method which is found by the VM.
Kent is right, there is a subtle difference in between compile/runtime protected checks (by the spec) and our behavior is the proper one. The compiler static check is fine. Though I understand this behavior to be counter intuitive, but this is enforced by the Java language spec. Closing