什么是双大括号初始化语法({{…}})在Java?


当前回答

正如lukas Eder指出的那样,必须避免对集合进行双括号初始化。

它创建了一个匿名的内部类,并且由于所有内部类都保留了对父实例的引用,所以如果这些集合对象被其他对象引用,而不仅仅是声明的对象引用,那么它可以(99%可能会)防止垃圾收集。

Java 9引入了方便的方法List。的集合。的,和地图。的,应该用它代替。它们比双括号初始化式更快更有效。

其他回答

第一个大括号创建了一个新的匿名类,第二组大括号创建了一个实例初始化器,类似于静态块。

正如其他人指出的那样,使用它并不安全。

但是,您总是可以使用这个替代方法来初始化集合。

Java 8

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

Java 9

List<String> list = List.of("A", "B", "C");

在其他用途中,它是初始化集合的快捷方式。了解更多…

双大括号初始化创建一个从指定类派生的匿名类(外大括号),并在该类中提供一个初始化程序块(内大括号)。如。

new ArrayList<Integer>() {{
   add(1);
   add(2);
}};

注意,使用这种双大括号初始化的效果是创建匿名的内部类。创建的类有一个隐式this指针指向周围的外部类。虽然通常不是问题,但在某些情况下,例如序列化或垃圾收集时,它可能会导致痛苦,值得注意这一点。

这似乎与flash和vbscript中流行的with关键字相同。这是一种改变事物的方法,仅此而已。

关于双大括号初始化的有趣应用,请参阅这里的Dwemthy 's Array in Java。

摘录

private static class IndustrialRaverMonkey
  extends Creature.Base {{
    life = 46;
    strength = 35;
    charisma = 91;
    weapon = 2;
  }}

private static class DwarvenAngel
  extends Creature.Base {{
    life = 540;
    strength = 6;
    charisma = 144;
    weapon = 50;
  }}

现在,准备好迎接香肠味和培根味的大战吧!