Java中ArrayList声明中的奇怪语法

6

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

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

起初,我以为这是语法错误,但令我惊讶的是,代码在编译和运行时都没有出现错误。

我有以下问题:

  • Java中是否有关于此声明的标准定义和文档?
  • 当这段代码被编译时会发生什么?

请指向相关文献。


谢谢您指向上述问题。 - Bhoot
2个回答

2

这将创建一个带有自定义初始化器(请参见初始化实例成员)的匿名类:

通常情况下,您会在构造函数中放置代码以初始化实例变量。有两种替代方法可以使用来初始化实例变量:初始化块和final方法。 实例变量的初始化块看起来就像静态初始化块,但没有static关键字:

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

当您需要一个已经包含成员的列表时,这很方便,但编译时会产生更多的代码,因为匿名类实际上被编译为一个(全局)类,该类扩展了ArrayList

我最近读到了这篇文章,与此相关:

首先要注意的是,Java运行时根本不理解内部类。无论内部类是命名的还是匿名的,都使用烟幕和镜子的程序将内部类转换为全局类。如果该类有名称,则编译器生成类文件,其名称的格式为[outer]$[inner]——$是Java中的合法标识符。对于内部类,生成的类文件仅仅是编号。因此,当在本文开头的线程示例被编译时,我们得到一个名为Test$1.class的类文件。数字'1'表示这是在类Test中定义的第一个匿名类。


0

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

除非有充分的理由,否则不要这样做。请使用:

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

或者如果您需要可变性:

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

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

但是在这两种方法之间有一个要牢记的区别。你的方法创建了一个不可修改的列表。如果列表不应该被修改,那么你的解决方案就是应该选择的。 - SubOptimal
@subopt 请阅读并编辑 :) - Bohemian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接