我花了半个小时来解决这个问题,我已经设法修复了我的代码,但我并不完全理解发生了什么,并想知道是否有人可以对它进行说明。
我有一个 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;
为什么会有所作为?我完全被这个困惑了。
答案 0 :(得分:13)
这是因为null
到myDBIndex
的分配是在
private static DBConnection myDBConnection = spawnDBConnection();
e.g。覆盖spawnDBConnection
序列是:
myDBConnection
,myDBIndex
初始化myDBConnection = spawnDBConnection();
其中包括致电spawnDBConnection
并将返回值分配给myDBConnection
myDBIndex
(带有空值)在第二个示例中,第3步不存在。
答案 1 :(得分:7)
为什么会有所作为?我完全被这个困惑了。
spawnDBConnection
的初始化程序正在运行,然后 myDBIndex
的初始化程序正在运行。 myDBIndex
的初始值设定项将值设置为null。当 spawnDBConnection
将其设置为非空值后发生,最终结果是它为空。
尽量不要这样做 - 静态初始化程序调用的方法设置其他静态变量很奇怪。
答案 2 :(得分:1)
这是生成的static
初始化程序块中发生的情况:
static {
myDBConnection = spawnDBConnection();
myDBIndex = null;
}
我希望现在很清楚。
答案 3 :(得分:0)
据我所知,如果您在字段之前定义方法确实有效,那么在初始化时,类从顶部解析:
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