什么是双大括号初始化语法({{…}})在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;
}}
现在,准备好迎接香肠味和培根味的大战吧!
第一个大括号创建了一个新的匿名类,第二组大括号创建了一个实例初始化器,类似于静态块。
正如其他人指出的那样,使用它并不安全。
但是,您总是可以使用这个替代方法来初始化集合。
Java 8
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
Java 9
List<String> list = List.of("A", "B", "C");
为了避免双大括号初始化的所有负面影响,例如:
打破了“平等”的兼容性。 使用直接赋值时不执行检查。 可能存在内存泄漏。
做下面的事情:
创建单独的“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中的所有示例
正如lukas Eder指出的那样,必须避免对集合进行双括号初始化。
它创建了一个匿名的内部类,并且由于所有内部类都保留了对父实例的引用,所以如果这些集合对象被其他对象引用,而不仅仅是声明的对象引用,那么它可以(99%可能会)防止垃圾收集。
Java 9引入了方便的方法List。的集合。的,和地图。的,应该用它代替。它们比双括号初始化式更快更有效。
我认为有必要强调的是,在Java中没有“双大括号初始化”这样的东西。甲骨文网站没有这个术语。在这个例子中,有两个特性一起使用:匿名类和初始化程序块。开发人员似乎已经忘记了旧的初始化程序块,并在这个主题中引起了一些混乱。引用自Oracle文档:
实例变量的初始化块看起来就像静态初始化块,但是没有static关键字:
{
// whatever code is needed for initialization goes here
}