据我所知,“静态初始化块”是用来设置静态字段的值,如果它不能在一行中完成。
但我不明白为什么我们需要一种特殊的积木。例如,我们将一个字段声明为静态(没有赋值)。然后写几行代码,生成并赋值给上面声明的静态字段。
为什么我们需要这些行在一个特殊的块,如:static{…}?
据我所知,“静态初始化块”是用来设置静态字段的值,如果它不能在一行中完成。
但我不明白为什么我们需要一种特殊的积木。例如,我们将一个字段声明为静态(没有赋值)。然后写几行代码,生成并赋值给上面声明的静态字段。
为什么我们需要这些行在一个特殊的块,如:static{…}?
当前回答
当您实际上不想将值赋给任何东西时,例如在运行时只加载某个类一次时,它也很有用。
E.g.
static {
try {
Class.forName("com.example.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
}
}
嘿,还有一个好处,你可以用它来处理异常。想象一下getStuff()在这里抛出了一个异常,该异常实际上属于一个catch块:
private static Object stuff = getStuff(); // Won't compile: unhandled exception.
那么静态初始化式在这里很有用。您可以在那里处理异常。
另一个例子是事后做一些在分配过程中不能做的事情:
private static Properties config = new Properties();
static {
try {
config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
} catch (IOException e) {
throw new ExceptionInInitializerError("Cannot load properties file.", e);
}
}
回到JDBC驱动程序示例,任何像样的JDBC驱动程序本身也使用静态初始化器在DriverManager中注册自己。还有这个和这个答案。
其他回答
有几个实际的原因,它必须存在:
初始化静态final成员,其初始化可能引发异常 用计算值初始化静态final成员
人们倾向于使用静态{}块作为一种方便的方式来初始化类在运行时所依赖的东西——比如确保特定的类被加载(例如JDBC驱动程序)。这可以通过其他方式来实现;然而,我上面提到的两件事只能用静态{}块这样的构造来完成。
在静态块中构造对象之前,可以为一个类执行一次代码。
E.g.
class A {
static int var1 = 6;
static int var2 = 9;
static int var3;
static long var4;
static Date date1;
static Date date2;
static {
date1 = new Date();
for(int cnt = 0; cnt < var2; cnt++){
var3 += var1;
}
System.out.println("End first static init: " + new Date());
}
}
作为补充,就像@Pointy说的
“静态”部分中的代码将在类加载时执行 时间,在构造类的任何实例之前(以及在 任何静态方法都从其他地方调用)。
它应该将System.loadLibrary("I_am_native_library")添加到静态块中。
static{
System.loadLibrary("I_am_a_library");
}
它将保证在相关库加载到内存之前不调用本机方法。
根据oracle的loadLibrary:
如果使用相同的库名多次调用此方法, 第二次和随后的调用将被忽略。
所以很意外地,把系统。不使用loadLibrary以避免库被多次加载。
我认为静态块只是语法糖。你不能用静态块做什么,也不能用其他任何东西。
重复使用这里发布的一些例子。
这段代码可以在不使用静态初始化器的情况下重写。
方法1:使用静态
private static final HashMap<String, String> MAP;
static {
MAP.put("banana", "honey");
MAP.put("peanut butter", "jelly");
MAP.put("rice", "beans");
}
方法2:无静电
private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
HashMap<String, String> ret = new HashMap<>();
ret.put("banana", "honey");
ret.put("peanut butter", "jelly");
ret.put("rice", "beans");
return ret;
}
非静态块:
{
// Do Something...
}
每次构造类的实例时调用。静态块只被调用一次,当类本身初始化时,不管你创建了多少这种类型的对象。
例子:
public class Test {
static{
System.out.println("Static");
}
{
System.out.println("Non-static block");
}
public static void main(String[] args) {
Test t = new Test();
Test t2 = new Test();
}
}
这个打印:
Static
Non-static block
Non-static block