Issue with static code in Android

2019-07-14 07:14发布

问题:

I am building my own class, which is similar to an Enum. Here's the code:

public final class MyClass {
    public final static MyClass V1 = new MyClass("v1");
    public final static MyClass V2 = new MyClass("v2");
    public final static MyClass V3 = new MyClass("v3");

    private static Map<String, MyClass> values;
    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()]);
    }

    public static MyClass valueOf(String key) {        
        return values.get(key);    
    }

    public String getName() {        
        return name;    
    }

    public String toString() { 
        return getName(); 
    }

    public static void print() {
        Iterator<Map.Entry<String, MyClass>> i = values.entrySet().iterator();
        while (i.hasNext()) {
            String key = i.next().getKey();
            System.out.println(MyClass.class.getSimpleName() + ": " + key + ", " + values.get(key));
        }
    }
}

I am observing a weird behavior: when I try to invoke MyClass.valueOf("v1") I get null. I tried to debug and:

  • the constructor is invoked long before valueOf is invoked (when I invoke print, it gets invoked 3 times)
  • values gets populated (last constructor invocation, of course, takes the map size to 3, as expected.
  • when in valueOf, values is empty

====UPDATE

ONLY if I am in debug mode and put a breakpoint in the print method, then I can see the "enum-like-class" values printed in the console. When I do htis, valueOf returns the correct results.

What's happening?

回答1:

Currently, the best way I found to tackle the issue is to move values definition and initialization before the other static variables. This way, it gets initialized before the constructors are invoked.

Look at this: Static initializer not called on Activity creation