Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing protected method of anonymous object vs by a named reference

Tags:

java

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?

like image 833
Alexey R. Avatar asked Dec 07 '25 09:12

Alexey R.


1 Answers

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.

like image 89
Jon Skeet Avatar answered Dec 09 '25 21:12

Jon Skeet