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


当前回答

为了避免双大括号初始化的所有负面影响,例如:

打破了“平等”的兼容性。 使用直接赋值时不执行检查。 可能存在内存泄漏。

做下面的事情:

创建单独的“Builder”类,专门用于双大括号初始化。 用默认值声明字段。 将对象创建方法放在该类中。

例子:

public class MyClass {
    public static class Builder {
        public int    first  = -1        ;
        public double second = Double.NaN;
        public String third  = null      ;

        public MyClass create() {
            return new MyClass(first, second, third);
        }
    }

    protected final int    first ;
    protected final double second;
    protected final String third ;

    protected MyClass(
        int    first ,
        double second,
        String third
    ) {
        this.first = first ;
        this.second= second;
        this.third = third ;
    }

    public int    first () { return first ; }
    public double second() { return second; }
    public String third () { return third ; }
}

用法:

MyClass my = new MyClass.Builder(){{ first = 1; third = "3"; }}.create();

优点:

简单易用。 不要破坏“对等”的兼容性。 您可以在创建方法中执行检查。 无内存泄漏。

缺点:

一个也没有。

因此,我们有了有史以来最简单的java构建器模式。

查看github: java-sf-builder-simple-example中的所有示例

其他回答

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

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 8

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

Java 9

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

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

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