我知道静态初始化块是如何工作的。
谁能告诉我它的一些典型用途。
7 回答
当您想在一个地方初始化一个或多个静态变量时
它很有用,因为您可以应用异常处理,而这对于内联初始化是不可能的。
例如:
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 所指出的,静态初始化块会降低代码的可读性,因此请谨慎使用它们。静态方法更透明地做同样的事情。
尽量避免使用静态初始化块。相反,您可以使用私有静态初始化函数,这将使您的代码更干净。
我将参考@Bozho 的例子。
不要做
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
改为使用
public static Configuration configuration = createConfiguration();
或者
public static Configuration configuration = YourConfiguration.create();
它们通常与JNI代码结合使用,以确保加载所需的本机库:
class MyJniConnection {
public static native void myJniCall();
static {
System.load("native.dll");
}
}
- 初始化集合静态字段,如 Map、List、Set 等
- 初始化同样是静态的基于 setter 的对象
JDBC 驱动程序是一个流行的例子
为什么需要Class.forName()
将驱动程序加载到内存中。答案很简单。正如 JDBC 规范中规定的那样,所有 JDBC都有一个静态块,以便在加载类后立即Driver
注册自己。像这样的东西:DriverManager
Driver
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
.
它们可用于创建 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
- 静态块:-当我们想在加载类时执行代码时,我们可以将代码放在静态块中......
- init :- 当我们想在类的对象初始化时执行代码时,我们可以将代码放在 init 块中......