Home > front end >  Accessing protected method of anonymous object vs by a named reference
Accessing protected method of anonymous object vs by a named reference

Time:07-22

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.

  •  Tags:  
  • java
  • Related