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


当前回答

第一个大括号创建了一个新的匿名内部类。 第二组大括号创建了一个实例初始化器,类似于Class中的static block。

例如:

   public class TestHashMap {
    public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<String,String>(){
        {
            put("1", "ONE");
        }{
            put("2", "TWO");
        }{
            put("3", "THREE");
        }
        };
        Set<String> keySet = map.keySet();
        for (String string : keySet) {
            System.out.println(string+" ->"+map.get(string));
        }
    }
    
}

它是如何工作的

第一个大括号创建了一个新的匿名内部类。这些内部类能够访问它们的父类的行为。因此,在本例中,我们实际上是在创建HashSet类的子类,因此这个内部类能够使用put()方法。

第二组大括号只是实例初始化器。如果你还记得核心java概念,那么你可以很容易地将实例初始化器块与静态初始化器关联起来,因为类似struct的大括号。唯一的区别是静态初始化器添加了static关键字,并且只运行一次;不管你创建了多少个对象。

more

其他回答

关于双大括号初始化的有趣应用,请参阅这里的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;
  }}

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

你是说像这样的事?

List<String> blah = new ArrayList<String>(){{add("asdfa");add("bbb");}};

这是在创建时初始化数组列表(hack)

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

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

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

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

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

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

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