In Hidden Features of Java the top answer mentions Double Brace Initialization, with a very enticing syntax:
Set<String> flavors = new HashSet<String>() {{
add("vanilla");
add("strawberry");
add("chocolate");
add("butter pecan");
}};
This idiom creates an anonymous inner class with just an instance initializer in it, which "can use any [...] methods in the containing scope".
Main question: Is this as inefficient as it sounds? Should its use be limited to one-off initializations? (And of course showing off!)
Second question: The new HashSet must be the "this" used in the instance initializer ... can anyone shed light on the mechanism?
Third question: Is this idiom too obscure to use in production code?
Summary: Very, very nice answers, thanks everyone. On question (3), people felt the syntax should be clear (though I'd recommend an occasional comment, especially if your code will pass on to developers who may not be familiar with it).
On question (1), the generated code should run quickly. The extra .class files do cause jar file clutter, and slow program startup slightly (thanks to @coobird for measuring that). @Thilo pointed out that garbage collection can be affected, and the memory cost for the extra loaded classes may be a factor in some cases.
Question (2) turned out to be most interesting to me. If I understand the answers, what's happening in DBI is that the anonymous inner class extends the class of the object being constructed by the new operator, and hence has a "this" value referencing the instance being constructed. Very neat.
Overall, DBI strikes me as something of an intellectual curiousity. Coobird and others point out you can achieve the same effect with Arrays.asList, varargs methods, Google Collections, and the proposed Java 7 Collection literals. Newer JVM languages like Scala, JRuby, and Groovy also offer concise notations for list construction, and interoperate well with Java. Given that DBI clutters up the classpath, slows down class loading a bit, and makes the code a tad more obscure, I'd probably shy away from it. However, I plan to spring this on a friend who's just gotten his SCJP and loves good natured jousts about Java semantics! ;-) Thanks everyone!
7/2017: Baeldung has a good summary of double brace initialization and considers it an anti-pattern.
12/2017: @Basil Bourque notes that in the new Java 9 you can say:
Set<String> flavors = Set.of("vanilla", "strawberry", "chocolate", "butter pecan");
That's for sure the way to go. If you're stuck with an earlier version, take a look at Google Collections' ImmutableSet.
flavors
to be aHashSet
, but alas it is an anonymous subclass. – DimercaprolSet<String> flavors = Set.of( "vanilla" , "strawberry" , "chocolate" , "butter pecan" ) ;
– SpitfireList.of
is not the same. – FalkStream.of("vanilla", "strawberry").collect(Collectors::toSet)
– Parochial