Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Taking the following test class:</p> <pre><code>public class Test { public void test() { Set&lt;String&gt; flavors = new HashSet&lt;String&gt;() {{ add("vanilla"); add("strawberry"); add("chocolate"); add("butter pecan"); }}; } } </code></pre> <p>and then decompiling the class file, I see:</p> <pre><code>public class Test { public void test() { java.util.Set flavors = new HashSet() { final Test this$0; { this$0 = Test.this; super(); add("vanilla"); add("strawberry"); add("chocolate"); add("butter pecan"); } }; } } </code></pre> <p>This doesn't look terribly inefficient to me. If I were worried about performance for something like this, I'd profile it. And your question #2 is answered by the above code: You're inside an implicit constructor (and instance initializer) for your inner class, so "<code>this</code>" refers to this inner class.</p> <p>Yes, this syntax is obscure, but a comment can clarify obscure syntax usage. To clarify the syntax, most people are familiar with a static initializer block (JLS 8.7 Static Initializers):</p> <pre><code>public class Sample1 { private static final String someVar; static { String temp = null; ..... // block of code setting temp someVar = temp; } } </code></pre> <p>You can also use a similar syntax (without the word "<code>static</code>") for constructor usage (JLS 8.6 Instance Initializers), although I have never seen this used in production code. This is much less commonly known.</p> <pre><code>public class Sample2 { private final String someVar; // This is an instance initializer { String temp = null; ..... // block of code setting temp someVar = temp; } } </code></pre> <p>If you don't have a default constructor, then the block of code between <code>{</code> and <code>}</code> is turned into a constructor by the compiler. With this in mind, unravel the double brace code:</p> <pre><code>public void test() { Set&lt;String&gt; flavors = new HashSet&lt;String&gt;() { { add("vanilla"); add("strawberry"); add("chocolate"); add("butter pecan"); } }; } </code></pre> <p>The block of code between the inner-most braces is turned into a constructor by the compiler. The outer-most braces delimit the anonymous inner class. To take this the final step of making everything non-anonymous:</p> <pre><code>public void test() { Set&lt;String&gt; flavors = new MyHashSet(); } class MyHashSet extends HashSet&lt;String&gt;() { public MyHashSet() { add("vanilla"); add("strawberry"); add("chocolate"); add("butter pecan"); } } </code></pre> <p>For initialization purposes, I'd say there is no overhead whatsoever (or so small that it can be neglected). However, every use of <code>flavors</code> will go not against <code>HashSet</code> but instead against <code>MyHashSet</code>. There is probably a small (and quite possibly negligible) overhead to this. But again, before I worried about it, I would profile it.</p> <p>Again, to your question #2, the above code is the logical and explicit equivalent of double brace initialization, and it makes it obvious where "<code>this</code>" refers: To the inner class that extends <code>HashSet</code>.</p> <p>If you have questions about the details of instance initializers, check out the details in the <a href="http://java.sun.com/docs/books/jls/download/langspec-3.0.pdf" rel="noreferrer">JLS</a> documentation.</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