7

我刚刚花了半个小时来解决这个问题,我已经设法修复了我的代码,但我并不完全理解发生了什么,并且想知道是否有人可以对此有所了解。

我有一个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() 方法为myDBConnectionmyDBIndex分配一个值。这很完美,我的程序的第一行输出总是“数据库连接完成”,在 spawnDBConnection() 方法的末尾,myDBConnection 或 myDBIndex 都不是空的,一切都应该是这样。

我的外部程序如下所示;

//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,没有进行其他分配,现在它是 null :(

简单的解决方法是删除“= null”,因此字段声明现在看起来像;

private static DBIndex myDBIndex;

为什么会有所作为?我被这个彻底搞糊涂了。

4

4 回答 4

13

那是因为nullto的分配myDBIndex是在之后完成的

private static DBConnection myDBConnection = spawnDBConnection();

例如覆盖分配spawnDBConnection

顺序是:

  1. 声明字段myDBConnectionmyDBIndex
  2. 初始化myDBConnection = spawnDBConnection();

    其中包括调用spawnDBConnection和分配返回值到myDBConnection

  3. 初始化myDBIndex(为空)

在您的第二个示例中,第三步不存在。

于 2012-07-24T12:52:06.770 回答
7

为什么会有所作为?我被这个彻底搞糊涂了。

的初始化程序spawnDBConnection正在运行,然后初始化程序myDBIndex正在运行。myDBIndex将值设置为 null的初始化程序。由于这是在将其设置为非空值之后发生的,因此最终结果是它为空。 spawnDBConnection

尽量不要这样做 - 静态初始化程序调用的方法设置其他静态变量很奇怪。

于 2012-07-24T12:52:22.403 回答
1

static这是在生成的初始化程序块中发生的事情:

static {
   myDBConnection = spawnDBConnection();
   myDBIndex = null;
}

我希望现在很清楚。

于 2012-07-24T12:51:52.337 回答
0

据我所知,如果您在字段起作用之前定义您的方法,则在初始化时,类将从 top 解析

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-24T13:04:22.037 回答