首先,感谢您提出这个有趣的问题。我很感兴趣,以至于我忍不住要看一下字节码。这是字节码
TestNested:
Compiled from "TestNested.java" public class a.TestNested { public a.TestNested(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc_w #2 // class a/TestNested$A 3: astore_1 4: aload_1 5: invokevirtual #3 // Method java/lang/Class.getDeclaredConstructors:()[Ljava/lang/reflect/Constructor; 8: astore_2 9: aload_2 10: arraylength11: istore_3 12: iconst_0 13: istore 4 15: iload 4 17: iload_3 18: if_icmpge 41 21: aload_2 22: iload 4 24: aaload 25: astore 5 27: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 30: aload 5 32: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 35: iinc 4, 1 38: goto 15 41: new#2 // class a/TestNested$A 44: dup 45: new#6 // class a/TestNested 48: dup 49: invokespecial #7 // Method "<init>":()V 52: dup 53: invokevirtual #8 // Method java/lang/Object.getClass:()Ljava/lang/Class; 56: pop 57: bipush 123 59: aconst_null60: invokespecial #9 // Method a/TestNested$A."<init>":(La/TestNested;ILa/TestNested$1;)V 63: astore_2 64: return }如您所见,构造函数
a.TestNested$A(a.TestNested,int,a.TestNested$1)是从您的
main方法中调用的。此外,
null作为
a.TestNested$1参数的值传递。
因此,让我们看一下神秘的匿名类
a.TestNested$1:
Compiled from "TestNested.java"class a.TestNested$1 {}奇怪-我本来希望这堂课能真正做些事。要了解它,让我们看一下
a.TestNested$A:类a.TestNested $ A {final
a.TestNested this $ 0;
a.TestNested$A(a.TestNested); Code: 0: aload_0 1: aload_1 2: putfield #2 // Field this$0:La/TestNested; 5: aload_0 6: invokespecial #3 // Method java/lang/Object."<init>":()V 9: return private a.TestNested$A(a.TestNested, int); Code: 0: aload_0 1: aload_1 2: putfield #2 // Field this$0:La/TestNested; 5: aload_0 6: invokespecial #3 // Method java/lang/Object."<init>":()V 9: return a.TestNested$A(a.TestNested, int, a.TestNested$1); Code: 0: aload_0 1: aload_1 2: iload_2 3: invokespecial #1 // Method "<init>":(La/TestNested;I)V 6: return }
查看包可见的构造函数
a.TestNested$A(a.TestNested, int, a.TestNested$1),我们可以看到第三个参数被忽略了。
现在我们可以解释构造函数和匿名内部类。为了避免对私有构造函数的可见性限制,需要额外的构造函数。这个额外的构造函数只是委托给私有构造函数。但是,它不能具有与私有构造函数完全相同的签名。因此,添加了匿名内部类以提供唯一的签名,而不会与其他可能的重载构造函数发生冲突,例如带有署名
(int,int)或的构造函数
(int,Object)。由于仅需要此匿名内部类来创建唯一的签名,因此不需要实例化它,也不需要具有内容。



