代码之家  ›  专栏  ›  技术社区  ›  AlirezaAsadi

使用包含块初始值设定项的匿名类初始化静态ArrayList字段

  •  1
  • AlirezaAsadi  · 技术社区  · 6 年前

    我正在玩javadeathmatch游戏,遇到了一个我无法回答的问题。你能帮助我吗?

    public class DeathMatch {
        private static final List<String> NAMES = new ArrayList<>() {{
            add("John");
            System.out.println(NAMES);
        }};
    
        public static void main(String[] args) {
            //Nothing in particular
        }
    }
    

    在这种情况下,当我们运行jvm时,类将被加载,首先创建并初始化它的静态成员“names”,arraylist也通过一个匿名类(包括一个块初始化器)初始化。 但问题是我们在“this”引用和打印名称中添加了“john”,因此它显示为空。 如果我们这样做更改,代码将正确运行:

    System.out.println(this);
    

    而不是:

    System.out.println(NAMES);
    

    为什么会这样?

    3 回复  |  直到 6 年前
        1
  •  3
  •   rgettman    6 年前

    当使用“双大括号”初始化时,将创建 ArrayList 使用外部大括号,内部一对大括号表示实例初始值设定项,在这里您将调用 add 打印出来 NAMES 是的。但在你构建 阵列列表 ,和 阵列列表 尚未完工,也未转让给 姓名 但是。变量 姓名 仍有其默认值 null 是的。

    虽然语法看起来很漂亮,但是通常不值得创建一个匿名子类,只是为了便于眼睛初始化。

    相反,如果必须以静态方式执行此操作,则将列表内容的初始化移动到静态初始值设定项块,以便 姓名 引用时已初始化。

    private static final List<String> NAMES = new ArrayList<String>();
    static {
        NAMES.add("John");
        System.out.println(NAMES);
    }
    
        2
  •  1
  •   Michael    6 年前
    new ArrayList<>() {{
        add("John");
        System.out.println(NAMES);
    }};
    

    基本上可以认为

    new MyList();
    

    在哪里? MyList 定义为:

    class MyList extends ArrayList<String> {
        public MyList() {
            super();
            add("John");
            System.out.println(NAMES);
        }
    }
    

    事件的顺序是:

    1. 调用构造函数
    2. 将构造函数返回的对象赋给名为“names”的静态字段

    所以因为 System.out.println 发生 在构造函数中 ,称之为 NAMES 意思是任务还没有完成也不起作用,但是 this 是有效的。


    您应该选择下列选项之一(取决于Java版本和元素数量):

    private static final List<String> NAMES = Arrays.asList("John");
    private static final List<String> NAMES = List.of("John");
    private static final List<String> NAMES = Collections.singletonList("John");
    

    然后是用于打印的静态块:

    static {
        System.out.println(NAMES);
    }
    
        3
  •  0
  •   Chirag    6 年前

    初始化的原因尚未完成 List NAMES 所以你得到了 null 对于 姓名 但是得到 [John] 使用时 this 关键字,如果你在 main ,它将产生所需的输出。