6

起動すると、私のプログラムはすぐにExceptionInInitializerErrorをスローします。ソースはこのメソッドからのものです:

public static void errorMessage(String input) {
    System.err.println("[ERROR] " + form.format(date) + " - " + Thread.currentThread().getStackTrace()[3].getClassName() + ": " + input);
}

文字列のさまざまな部分を印刷したところ、form.format(date)を呼び出したときにのみエラーがスローされることがわかりました。nullと書いてあります。唯一の問題は、日付と形式の両方がこのメソッドのすぐ上で静的に宣言されていることです。

public static Date date = new Date();
public static DateFormat form = new SimpleDateFormat("HH:mm:ss");

いくつかのマイナーなバグ修正の後、エラーが突然スローされ始めました。何が間違っているのか、これで何かが間違っている可能性があるのか​​、私にはわかりません。つまり、同じクラスで静的に宣言された変数を呼び出しています。技術的には、nullであってはなりませんが、nullです。なぜこのエラーがスローされるのか、誰か考えがありますか?コンソール出力は次のとおりです。

java.lang.ExceptionInInitializerError
at A$$OpSystem.getOperatingSystem(A$.java:98)
at A_.<clinit>(A_.java:19)
Caused by: java.lang.NullPointerException
at A$.errorMessage(A$.java:72)
at A$.loadCursor(A$.java:84)
at A$.<clinit>(A$.java:62)
... 2 more
Exception in thread "main" 

ちなみに、A $ .OpSystem.getOperatingSystemは、A $ .errorMessage ...を呼び出すため、ここにのみ表示されています。

そして、私は以前にこの問題を抱えていました。静的に宣言された変数が、呼び出されたときにnullのままであると実際に宣言されなかったときでした。現在、nullであるとは想定されていませんが、nullです。だから私はそれを引き起こしているのか分かりません。アイデア?

しかし、これは静的変数が実際にどのようにロードされるかについて教育するのに良い時期だと思います...

編集:「loadCursor」を呼び出す静的カーソルオブジェクトを別のクラスに移動しても、例外はスローされないようです。何?

この状況をテストしましたが、エラーは返されませんか?

public class StaticMethodTesting {

public static int i = getInt();

public static int getInt() {
    return getAnotherInt();
}

public static int getAnotherInt() {
    return 0;
}

public static void main(String[]args) {
    System.out.println("Hi");
}
}
4

2 に答える 2

8

例外トレースを調べた後...

at A$.errorMessage(A$.java:72)
at A$.loadCursor(A$.java:84)
at A$.< clinit>(A$.java:62)

およびA$の初期化の前に、の静的フィールドの初期化が実行されていることが明らかになります。これは、論理的にasで失敗し、初期化されません。dateformloadCursorNullPointerExceptiondateform

問題は、自分とオブジェクトCursorを初期化するコードの前に、自分を初期化するコードを配置したことです。宣言時に割り当てられた静的フィールドは、Java言語仕様のセクション§8.3.2.1に従って、宣言順に初期化されます。dateform

詳細な初期化プロセス、特にセクション§12.4.2.9を読むと、...

次に、クラスのクラス変数初期化子と静的初期化子、またはインターフェイスのフィールド初期化子のいずれかを、単一のブロックであるかのようにテキスト順に実行します。


したがって、次のようなことをしている可能性があります。

static Cursor cursor = loadCursor();
static Date date = new Date();
static DateFormat form = new SimpleDateFormat("HH:mm:ss");

static Cursor loadCursor() {
  ...
  errorMessage("...");
  ...
}

loadCursorこれを機能させるには、前に呼び出すことはできず、初期化する必要があります。dateform


あなたの例が「エラー」を生成しない理由(え?)は、どちらのメソッドもまだ初期化されていないフィールドを参照しているためです。決してエラーではない同等の動作が必要な場合は、以下を参照してください(ここで実行されていることがわかります)。

import java.util.Random;

public final class Example {

  /* note if the below read: static final int value = rand.nextInt(),
     this would be considered an illegal forward reference to rand */
  private static final int value = next();
  private static final Random rand = new Random();

  private static int next() {
    return rand.nextInt();
  }

  public static void main(final String[] argv) { }
}

出力は次のようになります。

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
        at Example.next(Example.java:11)
        at Example.<clinit>(Example.java:7)
于 2012-08-15T03:24:20.627 に答える
0

ここで問題が発生していることがわかると思います

Thread.currentThread().getStackTrace()[3].getClassName() 

あなたはもっと何かをする必要があるかもしれません

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String className = stackTrace[Math.min(3, stackTrace.length - 1)].getClassName();

または同様の:P

于 2012-08-15T03:14:09.193 に答える