问题
My objective is to have a private static Properties
object in my class, to act as defaults when creating other Properties
objects needed by my application. The current implementation looks like this:
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);
}
}
}
Looking at it, it works, but it doesn't feel right.
How would you do it?
回答1:
There are basically two ways. First way is using the static block as you have shown (but then with an ExceptionInInitializerError instead of the RuntimeException
). Second way is using a static method which you call immediately on declaration:
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;
}
The ConfigurationException
can just be your custom class extending RuntimeException
.
I personally prefer the static
block because it doesn't make sense having a method which is executed only once ever in its life. But if you refactor the method so that it takes a filename and can be reused globally, then that would be more preferred.
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:
Instead of a generic RuntimeException, I would throw an ExceptionInInitializerError, which is ment for exacctly this purpose. From the API documentation: "Signals that an unexpected exception has occurred in a static initializer."
回答3:
Seems acceptable to me; load in the static initialiser, it gets called only when the class is referenced, and is only called once. I like it. The only thing I'd do is make it final
.
Well, aside from the exception. I'd try and avoid that somehow (I have in the back of my mind that you should avoid exceptions in those types of initialisers, but I could be wrong on that).
来源:https://stackoverflow.com/questions/2027244/what-is-the-best-way-to-initialize-a-complex-static-member-in-java