看看这个例子:
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();
}
}
使用javap,我们可以查看为此代码生成的指令
主要方法:
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #2; //class Test
3: dup
4: invokespecial #3; //Method "<init>":()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."<init>":(LTest;)V
21: astore_2
22: return
}
内部类构造函数:
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."<init>":()V
9: return
}
一切都很简单 - 当调用 TestInner 构造函数时,java 将 Test 实例作为第一个参数 main:12 传递。不看那个TestInner应该有一个没有参数的构造函数。TestInner反过来只是保存对父对象Test$TestInner:2的引用。从实例方法调用内部类构造函数时,将自动传递对父对象的引用,因此您不必指定它。实际上,它每次都通过,但是当从外部调用时,它应该显式传递。
t.new TestInner();
- 只是向 TestInner 构造函数指定第一个隐藏参数的一种方法,而不是类型
方法() 等于:
public TestInner method(){
return this.new TestInner();
}
TestInner 等于:
class TestInner{
private Test this$0;
TestInner(Test parent){
this.this$0 = parent;
}
}