7

私はこのことを理解するのに30分を費やしました.コードを修正することができました.

手元のタスクに応じて他のさまざまなプログラムで使用されるいくつかの静的フィールド (データベース接続エンドポイントなど) を含む 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 も 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 ではなく、他の割り当ては行われておらず、現在は 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(null あり)

2 番目の例では、3 番目のステップは存在しません。

于 2012-07-24T12:52:06.770 に答える
7

なぜそれが違いを生んだのですか?私はこれに完全に混乱しています。

のイニシャライザspawnDBConnectionが実行され、次にのイニシャライザmyDBIndexが実行されました。myDBIndex値を null に設定するための初期化子。これは、null 以外の値に設定した後に spawnDBConnection発生したため、最終的な結果は null でした。

これを行わないようにしてください - 静的初期化子によって呼び出されるメソッドが他の静的変数を設定するのは奇妙です。

于 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 に答える