Java静态字段初始化
我刚刚花了半小时弄清楚这件事情,我已经设法修复了我的代码,但是我并不完全理解正在发生的事情,并想知道是否有人可以阐明它。Java静态字段初始化
我有一个utils的类型的类,它包含由根据手头的任务其他多种程序使用了一些静态字段(例如数据库连接的端点)。本质上是一个图书馆。
这是它以前的样子(虽然还是坏了);
//DBUtils.java
public final class DBUtils {
private static DBConnection myDBConnection = spawnDBConnection();
private static DBIndex myDBIndex = null;
private static DBConnection spawnDBConnection() {
//connect to the database
//assign a value to myDBIndex (by calling a method on the DBConnection object) <- IMPORTANT
//myDbIndex NOT NULL HERE
System.out.println("database connection completed");
//return the DBConnection object
}
public static searchDB(String name) {
//use the myDBIndex to find a row and return it
}
}
所以简单地说,我使用的是静态spawnDBConnection()方法来分配一个值都myDBConnection和myDBIndex。这是完美的,我的程序中的第一个输出行始终是“数据库连接已完成”,在spawnDBConnection()方法结束时,myDBConnection或myDBIndex都不为null,所有内容都应该如此。
我的外部程序看起来像这样;
//DoSomethingUsefulWithTheDatabase.java
public final class DoSomethingUsefulWithTheDatabase {
public static void main(String args[]) {
DBUtils.searchDB("John Smith"); //fails with NullPointerException on myDBIndex!
}
}
这次调用searchDB发生在spawnDBConnection结束后,我已经使用了标准输出广泛,显示这一点。但是,一旦进入searchDB方法,myDBIndex的值就是null!它是一个静态字段,并且在spawnDBConnection结束时它不为空,现在没有其他任务了,现在它是空的:(
简单的修复方法是删除“= null”,所以现在的字段声明看起来像等;
private static DBIndex myDBIndex;
为什么有所作为,我彻底被这个迷惑
这是因为null
到myDBIndex
的分配后
private static DBConnection myDBConnection = spawnDBConnection();
例如做覆盖在spawnDBConnection
顺序分配是:
- 申报领域
myDBConnection
,myDBIndex
-
初始化
myDBConnection = spawnDBConnection();
,其中包括呼叫
spawnDBConnection
和返回值赋值给myDBConnection
- 初始化
myDBIndex
(with null)
在第二个例子中,第三步不存在。
感谢您澄清这一点,它现在非常有意义。出于某种原因,我认为任何方法调用都会在“简单”分配后发生。 – lynks 2012-07-24 13:21:10
这是产生static
initalizer块会发生什么:
static {
myDBConnection = spawnDBConnection();
myDBIndex = null;
}
?
我希望现在很清楚。
为什么这会有所作为?我完全被这个弄糊涂了。
为spawnDBConnection
的初始化正在运行,然后为的myDBIndex
初始化正在运行。 myDBIndex
的初始化程序将该值设置为null。当发生后spawnDBConnection
将其设置为非空值时,最终结果为空。
尽量不要这么做 - 对于静态初始化程序调用的方法来设置其他静态变量很奇怪。
感谢您的回复,我知道当我写这篇文章时,在另一个静态变量中初始化一个静态变量是一件很奇怪的事情,我只是将代码放在一起进行一些快速测试。 – lynks 2012-07-24 13:10:48
至于我所知,如果你的领域之前定义你的方法它的工作,在初始化时,类是从顶部解析:
public class DbUtils {
private static String spawnDBConnection() {
System.out.println("database connection completed");
return "INIT";
}
private static String myDBConnection = spawnDBConnection();
private static int myDBIndex = 0;
public static void main(final String[] args) {
System.out.println(myDBConnection);
}
}
输出:
database connection completed
INIT
考虑制定你的静态'最后'。你将被迫分配一次,消除这种惊喜。 – 2012-07-24 12:52:47
这是一个可怕的噩梦 - 反模式你在这里做什么。您将类初始化耦合到数据库连接的获取。 – 2012-07-24 12:54:28
您不应静态初始化DBConnection。如果myDBConnection死了,你会在代码中开始使用DbUtils2吗? – 2012-07-24 12:58:32