2012-02-26 1 views
0

Когда конструктор использует ссылку на константу, которая создается с ленивым экземпляром, java выдает ExceptionInInitializerError (в частности, в строке «this (ClassA.INSTANCE1)»).Ленивое создание констант методом фабрики вызывает ошибку при использовании в конструкторе

public class ClassA { 
    public static final ClassA INSTANCE1 = get("INSTANCE1"); 
    public static final ClassA INSTANCE2 = get("INSTANCE2"); 

    private static final Map<String, ClassA> MULTITON_MAP = new HashMap<String, ClassA>(); 

    private String name; 

    private ClassA(String name) { 
     this.name = name; 
    } 

    public static ClassA get(String name) { 
     ClassA toReturn = MULTITON_MAP.get(name); 
     if (toReturn == null) { 
      toReturn = new ClassA(name); 
      MULTITON_MAP.put(name, toReturn); 
     } 
     return toReturn; 
    } 
} 

public class ClassB { 
    private ClassA type; 

    public ClassB() { 
     this(ClassA.INSTANCE1); 
    } 

    public ClassB(ClassA type) { 
     this.type = type; 
    } 

    public static void main(String[] args) { 
     new ClassB(); 
    } 
} 

Я решил проблему, удалив ленивый экземпляр и перемещая экземпляры в статический блок.

public class ClassA { 
    public static final ClassA INSTANCE1; 
    public static final ClassB INSTANCE2; 

    ... 

    static { 
     INSTANCE1 = new ClassA("INSTANCE1"); 
     INSTANCE2 = new ClassA("INSTANCE2"); 

     MULTITON_MAP.put("INSTANCE1", INSTANCE1); 
     MULTITON_MAP.put("INSTANCE2", INSTANCE2); 
    } 

    ... 
} 

Итак, на мой вопрос, почему Java не может обработать то, что я делал ранее. Что вызывает ошибку и почему?

Спасибо!

ответ

1

Я думаю, ваша проблема в том, что вы пытаетесь инициализировать INSTANCE1 до того MULTITON_MAP, но конкретизация INSTANCE1 зависит от MULTITON_MAP.

E.g. при звонке MULTITON_MAP.get(name); в get, MULTITON_MAP по-прежнему не имеется.

+0

Ах! Поэтому метод ClassA.get() вызывается до того, как ClassA был загружен, поэтому MULTITON_MAP не был создан? Я думал, что он будет создан при загрузке ClassA. –

+0

Это, но также 'INSTANCE1' и' INSTANCE2' и, по-видимому, они создаются до 'MULTITON_MAP' – MByD

+0

Хмм ... поэтому статические переменные создаются в том порядке, в котором они перечислены. Имеет смысл. –

1
private static final Map<String, ClassA> MULTITON_MAP = new HashMap<String, ClassA>(); 
public static final ClassA INSTANCE1 = get("INSTANCE1"); 
public static final ClassA INSTANCE2 = get("INSTANCE2"); 

Вы пытались инициализировать экземпляры перед инициализацией карты.

+0

Спасибо! Я не понимал, что это так просто. Лол –

Смежные вопросы