java中ArrayList声明中的奇怪语法

时间:2015-04-30 12:42:44

标签: java arraylist syntax

最近,我偶然发现了以下java语法:

ArrayList<String> nodes = new ArrayList<String>(){{add("n1");add("n2");}};

起初,我认为这是一个语法错误,但令我惊讶的是,代码没有给出编译或运行时错误。

我有以下问题:

  • Java中是否有此类声明的标准定义和文档?
  • 编译此代码会发生什么?

请指出相关文献。

2 个答案:

答案 0 :(得分:2)

这会创建一个包含自定义initializer的匿名类(请参阅初始化实例成员):

  

通常,您可以使用代码在构造函数中初始化实例变量。使用构造函数初始化实例变量有两种选择:初始化块和最终方法。   实例变量的初始化程序块看起来就像静态初始化程序块,但没有静态关键字:

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

当你想要一个已包含成员的列表时,它很方便,但在编译时产生更多代码,因为匿名类实际上被编译为扩展ArrayList的不同的(全局)类。

我最近阅读了与此事有关的this post

  

要注意的第一点是Java运行时根本不了解内部类。无论内部类是命名还是匿名,使用烟雾和镜像过程将内部类转换为全局类。如果类具有名称,则编译器生成名称格式为[outer] $ [inner]的类文件 - $是Java中的合法标识符。对于内部类,生成的类文件只是编号。因此,当编译本文开头的Thread示例时,我们最终会得到一个名为Test $ 1.class的类文件。数字“1”表示这是Test类中定义的第一个匿名类。

答案 1 :(得分:0)

这是一个实例块,它是在构造时执行的,是一个匿名子类。

除非有充分的理由,否则不要这样做。喜欢:

List<String> nodes = Arrays.asList("n1", "n2");

或者如果你需要可变性:

List<String> nodes = new ArrayList(Arrays.asList("n1", "n2"));

因为匿名类保留了对它所声明的类的包含实例的引用,这可能导致内存泄漏。