Say I have this abstract class:
package test.one;
public abstract class One {
protected abstract void whatever();
public void run(){
whatever();
}
}
And use it like this:
package test.two;
import test.one.One;
public class Three {
public static void main(String[] args){
One one = new One(){
@Override
protected void whatever(){
System.out.println("Do whatever..");
}
};
one.whatever();
}
}
This code fails on compilation which is pretty much expected.
test/two/Three.java:14: error: whatever() has protected access in One
one.whatever();
^
1 error
But the below code compiles successfully which seems surprisingly:
package test.two;
import test.one.One;
public class Two {
public static void main(String[] args){
new One(){
@Override
protected void whatever(){
System.out.println("Do whatever..");
}
}.whatever();
}
}
The difference is that in the latter case I'm accessing the method without a named reference. Why does the compiler allow such access?
CodePudding user response:
The difference is that in the latter case I'm accessing the method without a named reference. Why does the compiler allow such access?
No, the difference is that in the latter case you're accessing the method on the anonymous class rather than on a reference of type One
.
Leaving aside the oddities around protected access, you can see the difference very easily by just creating an anonymous class with a public method:
class Test {
public static void main(String[] args) {
// This is fine...
new Object() {
public void method() {
System.out.println("Called");
}
}.method();
// This is not, because Object doesn't contain a method called "method".
Object o = new Object() {
public void method() {
System.out.println("Called");
}
};
o.method();
}
}
As noted in comments, another way to see the same effect is to use var
, so that the compile-time type of the variable is the anonymous class.
Even private members within anonymous classes can be accessed within the containing scope, just as if they were normal nested classes.