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
}
};
}
}
A nested class that doesn't have any name is known as an anonymous class. An anonymous class must be defined inside another class. Hence, it is also known as an anonymous inner class. Its syntax is: class outerClass { // defining anonymous class object1 = new Type(parameterList) { // body of the anonymous class }; }
An anonymous class has access to the members of its enclosing class. An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final.
An anonymous inner class can be useful when making an instance of an object with certain "extras" such as overloading methods of a class or interface, without having to actually subclass a class. In simple words, a class that has no name is known as an anonymous inner class in Java.
Yes, by adding an initializer method that returns 'this', and immediately calling that method: int myVariable = 1; myButton. addActionListener(new ActionListener() { private int anonVar; public void actionPerformed(ActionEvent e) { // How would one access myVariable here? // It's now here: System.
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
.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With