Java静态字段初始化

时间:2012-07-24 12:49:50

标签: java initialization static-methods

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

我有一个 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;

为什么会有所作为?我完全被这个困惑了。

4 个答案:

答案 0 :(得分:13)

这是因为nullmyDBIndex的分配是在

之后完成的
private static DBConnection myDBConnection = spawnDBConnection();

e.g。覆盖spawnDBConnection

中的作业

序列是:

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

    其中包括致电spawnDBConnection并将返回值分配给myDBConnection

  3. 初始化myDBIndex(带有空值)
  4. 在第二个示例中,第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