【问题标题】:Lazy instantiation of constants through a factory method throws error when used in a constructor在构造函数中使用时,通过工厂方法延迟实例化常量会引发错误
【发布时间】:2012-02-26 15:07:28
【问题描述】:

当构造函数使用对正在延迟实例化的常量的引用时,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 无法处理我之前所做的事情。导致错误的原因是什么?

非常感谢!

【问题讨论】:

    标签: java exception static initialization


    【解决方案1】:

    我认为您的问题是您尝试在MULTITON_MAP 之前初始化INSTANCE1,但INSTANCE1 的实例化取决于MULTITON_MAP

    例如当您在get 中调用MULTITON_MAP.get(name); 时,MULTITON_MAP 仍然为空。

    【讨论】:

    • 啊!所以 ClassA.get() 方法是在 ClassA 加载之前调用的,所以 MULTITON_MAP 没有实例化?我以为它会在加载 ClassA 时被实例化。
    • 是,但也是 INSTANCE1INSTANCE2 显然,它们是在 MULTITON_MAP 之前实例化的
    • 嗯...所以静态变量按照它们列出的顺序进行实例化。有道理。
    【解决方案2】:
    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");
    

    您在初始化地图之前尝试初始化实例。

    【讨论】:

    • 谢谢!我没有意识到它是如此简单。大声笑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 2022-11-09
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多