在Java的隐藏特征中,上面的答案提到了双括号初始化,具有非常诱人的语法:
Set<String> flavors = new HashSet<String>() {{add("vanilla");add("strawberry");add("chocolate");add("butter pecan");}};
这个习惯用法创建一个匿名内部类,其中只有一个实例初始化器,它“可以使用包含范围内的任何[…]方法”。
主要问题:这听起来像低效吗?它的使用是否应该仅限于一次性初始化?(当然还有炫耀!)
第二个问题:新的HashSet必须是实例初始化器中使用的“this”……有人能解释一下这个机制吗?
第三个问题:这个习语是否太模糊而不能在生产代码中使用?
总结:非常非常好的答案,谢谢大家。关于问题(3),人们觉得语法应该很清晰(尽管我建议偶尔发表评论,特别是如果你的代码会传递给可能不熟悉它的开发人员)。
关于问题(1),生成的代码应该快速运行。额外的. class文件确实会导致jar文件混乱,并且程序启动会稍微慢一些(感谢@coobird测量)。@Thilo指出垃圾回收机制会受到影响,额外加载的类的内存成本在某些情况下可能是一个因素。
问题(2)对我来说是最有趣的。如果我理解答案,DBI中发生的事情是匿名内部类扩展了new运算符正在构建的对象的类,因此有一个引用正在构建的实例的“this”值。非常简洁。
总的来说,DBI在我看来是一种智力上的好奇心。Coobird和其他人指出,你可以通过Arrays.asList、varargs方法、Google Colltions和提议的Java7 Collection文字来达到同样的效果。较新的JVM语言,如Scala、JRuby和Groovy也为列表构造提供了简洁的符号,并且与Java很好地互操作。鉴于DBI会弄乱类路径,减缓类加载速度,并且使代码更加模糊,我可能会回避它。然而,我打算把这个告诉一个刚刚拿到SCJP并且喜欢关于Java语义学的善意争论的朋友!;-)谢谢大家!
7/2017: Baeldung有一个很好的总结的双括号初始化,并认为它是一个反模式。
2017年12月:@Basil Bourque指出,在新的Java9中,你可以说:
Set<String> flavors = Set.of("vanilla", "strawberry", "chocolate", "butter pecan");
这肯定是要走的路。如果您坚持使用早期版本,请查看Google集合的ImMutableSet。