【发布时间】:2012-09-06 18:00:05
【问题描述】:
我写了以下代码:
static {
/* Attempts to load JDBC driver */
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new DBConfigurationException("JDBC Driver not found.", e);
}
/* Attempts to load configuration */
conf = loadConfiguration(); //this may throw some subclasses of RuntimeException
}
因为我希望 JDBC 驱动程序和配置只加载一次。
我想在启动时做这样的事情(我会尽可能简化):
public static void main(String[] args) {
try {
// load the class that contains the code above
} catch (DBConfigurationException e) {
// display proper error message using JOptionPane, then quit
} catch (MissingConfigurationException e) {
// display proper error message using JOptionPane
// show a JDialog and allow user to input and store a configuration
} catch (InvalidConfigurationException e) {
// display proper error message using JOptionPane
// show a JDialog and allow user to input and store a configuration
}
/* if everything it's ok */
// do some other checks in order to decide which JFrame display first.
}
现在的问题是,如果发生异常,JVM 将抛出 ExceptionInInitializerError 广告并且不会构造该对象。
可能我仍然理解出了什么问题,抓住ExceptionInInitializerError(即使这听起来对我来说是错误的)并检查其原因(我仍然没有尝试这样做,但我认为这是可能的)。
我需要那个对象,因为如果异常是可恢复的(例如 MissingConfigurationException),程序将不会退出并且需要那个对象。
我应该避免使用静态初始化器吗? 我可以这样做:
private static final Configuration conf = null;
Constructor() {
if (conf == null) {
/* Attempts to load JDBC driver */
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new DBConfigurationException("JDBC Driver not found.", e);
}
/* Attempts to load configuration */
conf = loadConfiguration();
}
}
但即使这对我来说听起来也不正确:只有在第一次尝试使用时才会抛出异常(我知道这将在启动时进行,因为我必须进行检查),那是在加载类时。所以理论上第一种方法会更正确。 :\
我该怎么办?哪种方式更正确?
问题在于具有静态初始化器的类需要驱动程序和配置,所以在它们都可用之前不应该使用。 :\
【问题讨论】:
-
根据定义,
static{}块抛出的异常会生成 ExceptionInInitializer 并将类标记为不可用。这是它应该的方式(加上或减去一个小增量)。
标签: java exception static initialization classloader