【发布时间】:2011-01-12 12:50:06
【问题描述】:
我知道静态初始化块是如何工作的。
谁能告诉我它的一些典型用途。
【问题讨论】:
我知道静态初始化块是如何工作的。
谁能告诉我它的一些典型用途。
【问题讨论】:
尽量避免使用静态初始化块。相反,您可以使用私有静态初始化函数,这将使您的代码更干净。
我会参考@Bozho的例子。
不要做
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
改为使用
public static Configuration configuration = createConfiguration();
或
public static Configuration configuration = YourConfiguration.create();
【讨论】:
当你想在一个地方初始化一个或多个静态变量时
这很有用,因为您可以应用异常处理,而这是内联初始化无法实现的。
例如:
public static ImageIcon defaultIcon = ImageIO.read(..);
可以用
初始化public static ImageIcon defaultIcon;
static {
try {
defaultIcon = ImageIO.read(..);
} catch (IOException ex){
System.out.println("No default icon available");
}
}
另一个应用是复杂的初始化。例如,如果一个项目需要多行代码来初始化。假设您有一个配置:
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
第三种用法是初始化一些外部 API 基础设施。我当前项目的一个例子:
static {
org.apache.xml.security.Init.init();
}
但是,正如 Mykola Golubyev 所说,静态初始化块会降低代码的可读性,因此请谨慎使用。静态方法更透明地做同样的事情。
【讨论】:
【讨论】:
它们通常与JNI 代码结合使用,以确保加载所需的本机库:
class MyJniConnection {
public static native void myJniCall();
static {
System.load("native.dll");
}
}
【讨论】:
它们可用于创建 DSL,就像 JMock 所做的那样。例如,设置用户将被保存到数据库的期望:
Mockery context = new Mockery();
final Database database = context.mock(Database.class);
...
context.checking(new Expectations() {{
oneOf(database).save(user);
}});
// Rest of the test
【讨论】:
为什么需要Class.forName() 将驱动程序加载到内存中。答案很简单。在 JDBC 规范中规定,所有 JDBC Driver 都有一个静态块,以便在加载 Driver 类后立即向 DriverManager 注册自己。像这样的:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
所以,当你编写时(例如这里的 MySQL 驱动程序):
Class.forName("org.gjt.mm.mysql.Driver");
类加载器尝试加载和链接org.gjt.mm.mysql.Driver 类,如果成功,静态初始化块将被执行,Driver 将自己注册到DriverManager。
【讨论】:
【讨论】: