创建活动时未调用静态初始化程序

Man*_*anu 1 java static android

我的主要活动中有以下代码:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Fabric.with(this, new Crashlytics());
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        MyClass[] arr = MyClass.values();
        System.out.println(Arrays.deepToString(arr));
Run Code Online (Sandbox Code Playgroud)

我的类如下:

public class MyClass {

    public static MyClass A;
    public static MyClass B;
    public static MyClass C;

    static {
        System.out.println("Invoked");
        A = new MyClass("a");
        B = new MyClass("b");
        C = new MyClass("c");
    }

    private static Map<String, MyClass> values = null;
    private final String name;

    private MyClass(String name) {
        this.name = name;
        if (values == null)
            values = new HashMap<>();
        values.put(name, this);
    }

    public static MyClass[] values() {
        return values.values().toArray(new MyClass[values.size()]);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是values()触发 a NullPointerException,因为它values是 null,即静态初始化块似乎没有被调用。然而,控制台输出“Invoked”出现,因此初始化块确实被调用。

怎么了?

编辑:这个问题与此严格相关:Issues with static code in Android

And*_*ner 5

这是因为在静态初始化程序之后:该赋值将在静态初始化程序块之后private static Map<String, MyClass> values = null;运行,因此它被分配一个非空值,然后被清空。

values字段移到初始值设定项块之前。


顺便说一句,我会将实例的创建与将它们插入到地图中分离,以便消除创建MyClass. 您也可以在没有静态初始化块的情况下执行此操作:

public class MyClass {
    private static final Map<String, MyClass> values = new HashMap<>();

    public static final MyClass A = register(new MyClass("a"));
    public static final MyClass B = register(new MyClass("b"));
    public static final MyClass C = register(new MyClass("c"));

    private static MyClass register(MyClass instance) {
      values.put(instance.name, instance);
      return instance;
    }

    private MyClass(String name) {
      this.name = name;
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

实际上,我什至不会这样做:我会使用enum- 但我猜你的真实代码中有些东西会阻止你这样做。