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


当前回答

1-没有双括号这样的东西: 我想指出,没有双大括号初始化这样的东西。传统的初始化块只有一个大括号。第二个花括号块与初始化无关。答案说这两个大括号初始化了一些东西,但它不是这样的。

2-不只是匿名类,而是所有类: 几乎所有的答案都说它是在创建匿名内部类时使用的。我认为阅读这些答案的人会得到这样的印象,即这只在创建匿名内部类时使用。但它在所有课程中都被使用。读这些答案,它看起来像是一些全新的专门用于匿名类的特殊功能,我认为这是误导。

3- The purpose is just about placing brackets after each other, not new concept: Going further, this question talks about situation when second opening bracket is just after first opening bracket. When used in normal class usually there is some code between two braces, but it is totally the same thing. So it is a matter of placing brackets. So I think we should not say that this is some new exciting thing, because this is the thing which we all know, but just written with some code between brackets. We should not create new concept called "double brace initialization".

创建嵌套的匿名类与两个大括号无关: 我不同意创建太多匿名类的说法。你创建它们不是因为一个初始化块,而是因为你创建了它们。即使你没有使用两个大括号初始化,它们也会被创建,所以即使没有初始化,这些问题也会发生……初始化不是创建初始化对象的因素。

此外,我们不应该谈论使用这个不存在的东西“双括号初始化”,甚至是普通的单括号初始化所产生的问题,因为所描述的问题只是因为创建匿名类而存在,所以它与原始问题无关。但是所有的答案都给读者留下了这样的印象:创建匿名类并不是错误,而是这个邪恶的(不存在的)叫做“双括号初始化”的东西。

其他回答

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

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

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

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

你可以把一些Java语句作为循环来初始化集合:

List<Character> characters = new ArrayList<Character>() {
    {
        for (char c = 'A'; c <= 'E'; c++) add(c);
    }
};

Random rnd = new Random();

List<Integer> integers = new ArrayList<Integer>() {
    {
         while (size() < 10) add(rnd.nextInt(1_000_000));
    }
};

但这种情况对性能有影响,请检查此讨论

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

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

我认为有必要强调的是,在Java中没有“双大括号初始化”这样的东西。甲骨文网站没有这个术语。在这个例子中,有两个特性一起使用:匿名类和初始化程序块。开发人员似乎已经忘记了旧的初始化程序块,并在这个主题中引起了一些混乱。引用自Oracle文档:

实例变量的初始化块看起来就像静态初始化块,但是没有static关键字:

{
    // whatever code is needed for initialization goes here
}