Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First of all, thank you for this interesting question. I was so intrigued that I could not resist taking a look at the bytecode. This is the bytecode of <code>TestNested</code>:</p> <pre><code>Compiled from "TestNested.java" public class a.TestNested { public a.TestNested(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."&lt;init&gt;":()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: arraylength 11: 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 "&lt;init&gt;":()V 52: dup 53: invokevirtual #8 // Method java/lang/Object.getClass:()Ljava/lang/Class; 56: pop 57: bipush 123 59: aconst_null 60: invokespecial #9 // Method a/TestNested$A."&lt;init&gt;":(La/TestNested;ILa/TestNested$1;)V 63: astore_2 64: return } </code></pre> <p>As you can see, the constructor <code>a.TestNested$A(a.TestNested,int,a.TestNested$1)</code> is invoked from your <code>main</code> method. Furthermore, <code>null</code> is passed as the value of the <code>a.TestNested$1</code> parameter.</p> <p>So let's take a look at the mysterious anonymous class <code>a.TestNested$1</code>:</p> <pre><code>Compiled from "TestNested.java" class a.TestNested$1 { } </code></pre> <p>Strange - I would have expected this class to actually do something. To understand it, let's take a look at the constructors in <code>a.TestNested$A</code>: class a.TestNested$A { final a.TestNested this$0;</p> <pre><code> 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."&lt;init&gt;":()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."&lt;init&gt;":()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 "&lt;init&gt;":(La/TestNested;I)V 6: return } </code></pre> <p>Looking at the package-visible constructor <code>a.TestNested$A(a.TestNested, int, a.TestNested$1)</code>, we can see that the third argument is ignored. </p> <p>Now we can explain the constructor and the anonymous inner class. The additional constructor is required in order to circumvent the visibility restriction on the private constructor. This additional constructor simply delegates to the private constructor. However, it cannot have the exact same signature as the private constructor. Because of this, the anonymous inner class is added to provide a unique signature without colliding with other possible overloaded constructors, such as a constructor with signature <code>(int,int)</code> or <code>(int,Object)</code>. Since this anonymous inner class is only needed to create a unique signature, it does not need to be instantiated and does not need to have content.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload