初始化复杂静态值的最佳方法

时间:2014-05-29 16:42:03

标签: java optimization static enums

我有一个类可能需要一个基于enum类内容的大型但不变的数据结构。

我有兴趣知道的是,在static块中初始化它是否更好,或者我是否应该在实际访问数据的方法中初始化它(如果它从未实际使用过的话) )?

以下是一个例子:

public enum MyEnum {
    FOO ("foo"),
    BAR ("bar"),
    FOOBAR ("foo_bar");

    private final String otherName;

    private MyEnum (String otherName) {
        this.otherName = otherName;
    }

    private static final Map<String, MyEnum> otherNames = new HashMap<String, MyEnum>();
}

现在,我有两个初始化otherNames地图的选项,首先是使用静态块,如下所示:

static {
    for (MyEnum entry : MyEnum.values()) 
        otherNames.put(entry.otherName, entry);
}
public static MyEnum valueByOtherName (String otherName) {
    return otherNamesStatic.get(otherName);
}

或者我可以在第一次实际请求查找时初始化地图,如下所示:

public static MyEnum valueByOtherName(String otherName) {
    if (otherNames.isEmpty()) { // Or test against null or whatever
        for (MyEnum entry : MyEnum.values())
            otherNames.put(entry.otherName, entry);
    }
    otherNames.get(otherName);
}

特别是我有兴趣知道Java是否会优化static块,以便它可以在未来的运行中预先生成地图(因为它基于enum,所以如果它没有' t改变了,然后没有地图)或者每次加载时它都会运行静态代码,在这种情况下只在需要时才更有效吗?

2 个答案:

答案 0 :(得分:3)

每次加载类时都会执行静态块(而不是每次实例化对象时)。因此,除非您的环境使用多个类加载器,否则静态初始化块只会运行一次。

说完了,我建议使用更清洁的静态块(恕我直言)。

另请查看this answer以供参考。

答案 1 :(得分:1)

只要我理解Java,ClassLoader就会在加载类时调用静态初始化块,并且只在那一刻。所以:

  • 如果使用静态块,即使不使用valueByOtherName,如果使用MyEnum类,也确定至少调用一次,并且在jvm关闭之前永远不会再调用它(除非你有独立的ClassLoaders加载相同的类,至少应该 strange )。但是您在valueByOtherName
  • 中没有额外的测试
  • 如果在第一次查找时使用初始化,则只有在调用valueByOtherName时才会调用该块,并且永远不会再次调用构造。但是在每次调用valueByOtherName
  • 时都会有额外的测试

恕我直言,使用静态块要好得多。它更具可读性......