add()方法何时在集合中添加对象

时间:2018-10-07 14:45:45

标签: java arraylist collections static

我有两个问题。首先,请考虑以下代码。

public class Test{
    private static final List<String> var = new ArrayList<String>() {{
        add("A");
        add("B");
        System.out.println("INNER : " + var);
    }};

    public static void main(String... args){
        System.out.println("OUTER : " + var);
    }   
}

当我运行这段代码时,它会在输出下方显示

INNER : null
OUTER : [A, B]

任何人都可以详细说明为什么INNER为空并且在collection上恰好加上“ A”和“ B”时执行流吗?

第二,我在上面的代码中做了一些更改,并修改为下面的代码(只需将add方法放在第一个括号内)

public class Test{
    private static final List<String> var = new ArrayList<String>() {
        public boolean add(String e) { 
            add("A");
            add("B");
            System.out.println("INNER : " + var); return true; 
        };
    };

    public static void main(String... args){
        System.out.println("OUTER : "+var);
    }   
}

运行上面的代码后,我得到的结果是下面的

OUTER : []

查看此内容后,我对正在发生的事情一无所知。 INNER去了哪里?为什么不打印?不叫吗?

4 个答案:

答案 0 :(得分:13)

  1. 因为在{em>之前匿名类的实例引用已分配给ArrayList,所以执行了var匿名类的初始化程序块。

  2. 由于您从不调用add(String e)方法,因此不会执行该代码。如果这样做的话,将导致StackOverflowError,因为add("A")现在是递归调用。

答案 1 :(得分:5)

  1. 您创建的对象尚未在初始化过程中分配给var,请尝试以下操作:

    private static final List<String> var = new ArrayList<String>() {{
        add("A");
        add("B");
        System.out.println("THIS : " + this); // THIS : [A, B]
        System.out.println("INNER : " + var); // INNER : null
    }};
    
  2. 您只需覆盖add的{​​{1}}方法,就更麻烦了。它的工作原理是:

    ArrayList

答案 2 :(得分:2)

在代码段1中,您正在使用双括号初始化将项目添加到数组列表中。它基本上是一个带有实例初始化器的匿名内部类。由于在构造对象之前先打印var,所以它是null

在第二个代码段中,您将创建一个ArrayList的匿名类,该类提供add方法的实现。但是没有人调用ArrayList对象上的add方法。

编辑Andreas@提出的要点-即使您调用add方法,也会导致无限递归调用,从而产生StackOverflowError

参考:

Initialization of an ArrayList in one line

答案 3 :(得分:1)

在第一个代码中,在添加变量并在实例初始化器内打印列表之前,先打印变量,然后返回其构造函数。 因此它只能打印null

在第二个代码中,您重写add()以添加硬编码元素,但是从未在创建的实例上调用add()。因此add()不会打印任何内容,并且List实例中也不会添加任何内容。

要在列表中添加元素,通常需要在列表引用上调用add(),例如:

List<String> list = new ArrayList<>();
list.add("element A");
list.add("element B");

您不会为此要求创建匿名类。

如果您想使用更简单的语法,您仍然可以执行以下操作:

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