Consider the following article from the JLS: §15.9.5.1 When the anonymous class extends an inner class - then for the implicit constructor of the anonymous class - following is the rule regarding the body of the implicit constructor:
The constructor body consists of an explicit constructor invocation (§8.8.7.1) of the form
o.super(...), whereois the first formal parameter of the constructor, and the actual arguments are the subsequent formal parameters of the constructor, in the order they were declared.
Following is what we understand from this-:
o- is the instance of the class - that just encloses the super class of the anonymous class.- when we do
o.super(...)we are actually invoking the super class of the enclosing instance.
Consider the following program:
class A_ {
public A_(Boolean st){}
public class B_ {
public B_(Integer a){}
public class C_ {
public C_(String str){}
}
}
}
//when creating the anonymous constructor out of C - in a separate class:
public class ThisInAnonymousTesting {
public static void main(String[] args) {
A_.B_.C_ member =
new A_(true)
.new B_(23)
.new C_("Hey"){
};
}
}
Now when we decompile the anonymous class, we get the following:
/**
=== Anonymous class Declaration
*/
import A_.B_;
import A_.B_.C_;
final class ThisInAnonymousTesting$1 extends C_ {
// - Rule : the 1st argument is the class instance which is the enclosing instance
// of the Super class(C in this case) - ie B
ThisInAnonymousTesting$1(B_ x0, String str) {
x0.getClass();
//But the super() invocation here is for the super class - not for the enclosing instance
super(x0, str);
}
}
Following are my questions:
- Why do we need to do
o.super(...)- when we are already passing the initialized instance ofoto the anonymous class constructor?- ie
ogets created only when its super classes would have already been called. - The
super()call in the constructor is clearly trying to instantiate the classC_which is fine - as it is the super class for the current anonymous class.
- ie
- In the decompiled version, what is the need of
x0.getClass();- I mean why does JVM need to do thegetClass()?
Not sure if my interpretation of o.super() clause correct?
I think you misunderstood what
o.super(...)meant. Statements of the forms:are qualified superclass constructor invocations, and are specified in the explicit constructor invocations section of the JLS.
It does not invoke the superclass constructor of
o. It invokes the enclosing class's superclass constructor, withoas the enclosing instance.Here is a simple example:
If you do
Outer.OUTER2.new InnerSubclass();, the output is:OUTER1.super();there invokes the constructor ofInner(withOUTER1being the enclosing object), not the constructor ofOuter. Note that this is different from just doingsuper();, as that would be usingInnerSubclass's enclosing instance to invoke the superclass constructor, whatever that may be, not necessarilyOUTER1.So really what the spec is saying, is that the anonymous constructor will call the superclass' constructor, with the enclosing instance being the first parameter of the anonymous constructor. What is the first parameter of the anonymous constructor? This is stated just a few lines before:
In your case,
new A_(true).new B_(23).So the overall effect of this, is something like this:
Note:
ThisInAnonymousTesting$1 extends C_isn't valid Java, but it is allowed in bytecode.In the decompiled code, you see the syntax
super(x0, str);because there is no such thing as inner classes in bytecode. The enclosing instances of inner classes are all just translated to a private field, and assigned through the first parameter of the constructor. As a consequence,o.super(...)is really justsuper(o, ...)if you look at the byte code.Consider:
Bytecode for Outer$Inner.class is: