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