在Java中初始化复杂静态成员的最佳方法是什么?
我的目标是在我的类中有一个私有的静态在Java中初始化复杂静态成员的最佳方法是什么?,java,static-members,Java,Static Members,我的目标是在我的类中有一个私有的静态属性对象,在创建我的应用程序所需的其他属性对象时充当默认对象。当前的实现如下所示: public class MyClass { private static Properties DEFAULT_PROPERTIES = new Properties(); static { try { DEFAULT_PROPERTIES.load( MyClass.class.getRe
属性
对象,在创建我的应用程序所需的其他属性
对象时充当默认对象。当前的实现如下所示:
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);
}
}
}
看着它,它工作了,但感觉不对
你会怎么做?我似乎可以接受;在静态初始化器中加载时,只在引用类时调用它,并且只调用一次。我喜欢。我唯一要做的就是把它定为最终版本
嗯,除了例外。我会尝试以某种方式避免这种情况(我的想法是,您应该避免在这些类型的初始化器中出现异常,但我可能在这一点上是错误的)。我会抛出一个异常,而不是一般的运行时异常,这正是出于此目的。来自API文档:“表示静态初始值设定项中发生意外异常。”基本上有两种方法。第一种方法是使用如图所示的静态块(但随后使用一个而不是
运行时异常
)。第二种方法是使用静态方法,在声明时立即调用该方法:
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
的自定义类
我个人更喜欢静态
块,因为在它的生命周期中只有一次执行的方法是没有意义的。但是,如果您重构该方法,使其具有文件名并可以全局重用,那么这将是更可取的
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;
}
哦,我不知道。谢谢你的提示@jarnbjo我认为如果你提供一个指向API文档(ExceptionInitializer)的链接也会很有帮助:@sateesh:如果Java开发人员在API文档中找不到一个类,而我的答案中没有链接,那么他是时候学习如何做了。这实际上符合我的问题,因为我将创建更多具有相同模式的类,因此,创建一个抽象类并用
getProperties()
方法填充它是有意义的,这样它就可以在我的所有子类中重用。非常有用,谢谢!注意,我使用Thread\getContextClassLoader()
更改了加载属性文件的方式。别忘了在代码中也修改它。这会不会将资源加载到调用getProperties()
的类的同一个包中?我不确定是否理解您的意思。任何一种方式都是独立于包的。您可以在文件名中指定包。改进的方法只是类独立的,并且利用了已经加载调用类的类加载器。通过这种方式,您可以确保资源永远不会返回null,如果调用类没有被线程的类加载器加载,则可能会发生这种情况。我指的是org.example.MyClass.class.getResourceAsStream(“MyClass.properties”)
将打开资源ROOT/org/example/MyClass.properties
,使用ClassLoader
时,它将在ROOT/
目录中查找资源。我错了吗?