Rubiks
Rubiks

Reputation: 481

Anonymous class variables

I was experimenting with anonymous classes today. When I do System.out.println(super.x);, it prints 12, and when I use System.out.println(x); it prints 4. I thought super.x would print 4 and was wondering if someone could please explain to me why this is?

public class AnonClass {

    private int x = 1;

    public AnonClass(int x) {
        this.x = x;
    }

    public static void main(String[] args) {
        AnonClass test = new AnonClass(4);
        test.testMethod();
    }

    public void testMethod() {

        AnonClass anon = new AnonClass(12) {
            {
                System.out.println(super.x); //Prints 12
                System.out.println(x); //prints 4
            }
        };

    }
}

Upvotes: 10

Views: 455

Answers (2)

Andy Turner
Andy Turner

Reputation: 140318

When you define an anonymous class like this inside class AnonClass:

AnonClass anon =
    new AnonClass(12) {
      {
        System.out.println(super.x); //Prints 12
        System.out.println(x); //prints 4
      }
    };

the compiler will create a class something like this:

class AnonClass$1 extends AnonClass {
  final AnonClass enclosed;

  AnonClass$1(AnonClass enclosed, int x) {
    super(x);
    System.out.println(super.x);
    System.out.println(enclosed.x);
    this.enclosed = enclosed;
  }
}

and then invoke it like:

AnonClass anon = new AnonClass$1(this, 12);

Note that the invocation of the superconstructor (super(x);) happens before the contents of the instance initializer (the System.out.println lines).

As such, the field AnonClass.x is initialized to 12 by the superconstructor, and then its value is printed as 12 via System.out.println(super.x);.

Then, System.out.println(x) is actually referencing the x in the enclosing instance of AnonClass, whose value is 4.

The reason it doesn't print 12 again is that x is private; and as it says in JLS Sec 8.2:

Members of a class that are declared private are not inherited by subclasses of that class.

So there is no AnonClass$1.x to print; the only identifier in scope called x is AnonClass.x.

Upvotes: 11

bedrin
bedrin

Reputation: 4586

You have two classes here: regular class AnonClass and anonymous class AnonClass$1 extending AnonClass

Both these classes have x field

You also have two objects: one of type AnonClass instantiated inside main method with x = 4 and second one of type AnonClass$1 instantiated inside testMethod() with x = 12

When you're printing the value of super.x you are accessing the x field of second object; but the value of x belongs to the first object cause you class is not static and contains an implicit reference to instance of outer class

Reference: Nested Classes in Java

Upvotes: 1

Related Questions