I have the following code in my main Activity:
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));
MyClass is as follow:
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()]);
}
}
My issue is that values()
triggers a NullPointerException
, as values
is null, i.e. the static initialization block seems not to be invoked. Nevertheless, the console out "Invoked" appers, so the initialization block DOES get called.
What's wrong?
EDIT: this question is strictly related to this: Issue with static code in Android
It's because
private static Map<String, MyClass> values = null;
is after the static initializer: this assignment will be run after the static initializer block, so it is being assigned a non-null value, and then nulled out.Move the
values
field before the initializer block.BTW, I would decouple the creation of the instances from inserting them into the map, in order to remove the side effects when creating an instance of
MyClass
. You can also do it without a static initializer block:Actually, I wouldn't even do this: I'd use an
enum
- but I guess there is something in your real code that stops you from doing that.