在Java中初始化复杂静态成员的最佳方法是什么?

时间:2010-01-08 11:33:25

标签: java static-members

我的目标是在我的类中拥有一个私有静态Properties对象,在创建应用程序所需的其他Properties对象时充当默认值。目前的实现如下:

public class MyClass {
    private static Properties DEFAULT_PROPERTIES = new Properties();

    static {
        try {
           DEFAULT_PROPERTIES.load(
               MyClass.class.getResourceAsStream("myclass.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
 }

看着它,它有效,但感觉不对。

你会怎么做?

3 个答案:

答案 0 :(得分:5)

而不是一般的RuntimeException,我会抛出一个ExceptionInInitializerError,这是为了这个目的。从API文档:“表示静态初始化程序中发生了意外异常。”

答案 1 :(得分:4)

基本上有两种方式。第一种方法是使用您显示的静态块(但随后使用ExceptionInInitializerError而不是RuntimeException)。第二种方法是使用静态方法,您可以在声明时立即调用:

private static Properties DEFAULT_PROPERTIES = getDefaultProperties();

private static Properties getDefaultProperties() {
    Properties properties = new Properties();
    try {
        properties.load(MyClass.class.getResourceAsStream("myclass.properties"));
    } catch (IOException e) {
        throw new ConfigurationException("Cannot load properties file", e);
    }
    return properties;
}

ConfigurationException可以是扩展RuntimeException的自定义类。

我个人更喜欢static块,因为在生命中只有执行一次的方法没有意义。但是如果你重构方法以便它采用文件名并且可以全局重用,那么这将是更优选的。

private static Properties DEFAULT_PROPERTIES = SomeUtil.getProperties("myclass.properties");

// Put this in a SomeUtil class.
public static Properties getProperties(String filename) {
    Properties properties = new Properties();
    try {
        properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(filename));
    } catch (IOException e) {
        throw new ConfigurationException("Cannot load " + filename, e);
    }
    return properties;
}

答案 2 :(得分:0)

我似乎可以接受;在静态初始化器中加载,只有在引用类时才会调用它,并且只调用一次。我喜欢。我唯一要做的就是把它final

好吧,除了例外。我试着以某种方式避免这种情况(在我的脑海中,我应该避免在这些类型的初始化程序中出现异常,但我可能错了)。