In Java, I have just found out that the following code is legal:
KnockKnockServer newServer = new KnockKnockServer();
KnockKnockServer.re
Have a look at this example:
public class Test {
class TestInner{
}
public TestInner method(){
return new TestInner();
}
public static void main(String[] args) throws Exception{
Test t = new Test();
Test.TestInner ti = t.new TestInner();
}
}
Using javap we can view instructions generated for this code
Main method:
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #2; //class Test
3: dup
4: invokespecial #3; //Method "":()V
7: astore_1
8: new #4; //class Test$TestInner
11: dup
12: aload_1
13: dup
14: invokevirtual #5; //Method java/lang/Object.getClass:()Ljava/lang/Class;
17: pop
18: invokespecial #6; //Method Test$TestInner."":(LTest;)V
21: astore_2
22: return
}
Inner class constructor:
Test$TestInner(Test);
Code:
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:LTest;
5: aload_0
6: invokespecial #2; //Method java/lang/Object."":()V
9: return
}
Everything is simple - when invoking TestInner constructor, java passes Test instance as a first argument main:12. Not looking at that TestInner should have a no argument constructor. TestInner in its turn just saves reference to parent object, Test$TestInner:2. When you are invoking inner class constructor from an instance method, reference to parent object is passes automatically, so you do not have to specify it. Actually its passes every time, but when invoking from outside it should be passed explicitly.
t.new TestInner(); - is just a way to specify the first hidden argument to TestInner constructor, not a type
method() is equal to:
public TestInner method(){
return this.new TestInner();
}
TestInner is equal to:
class TestInner{
private Test this$0;
TestInner(Test parent){
this.this$0 = parent;
}
}