13

これは有効なコードではありません:

public class MyClass
{
    private static boolean yesNo = false;

    static
    {
        if (yesNo)
        {
            System.out.println("Yes");
            return; // The return statement is the problem
        }
        System.exit(0);
    }
}

これはばかげた例ですが、静的クラス コンストラクターではできませんreturn;。なんで?これには正当な理由がありますか?誰かがこれについてもっと知っていますか?

ですから、私がすべき理由は、そこでreturn構築を終了することです。

ありがとう

4

6 に答える 6

16

その理由は、初期化子がフィールド初期化と一緒に(インスタンス初期化子の場合はコンストラクターと一緒に)実行されるためだと思います。つまり、JVMは静的フィールドを初期化する場所を1つしか認識しないため、すべての初期化(ブロック単位かどうかに関係なく)はそこで実行する必要があります。

したがって、たとえば、クラスを作成する場合、次のようになります。

class A {
    static int x = 3;
    static {
        y = x * x;
    }
    static int z = x * x;
}

次に、実際には次のように記述したかのようになります。

class A {
    static int x, y, z;
    static {
        x = 3;
        y = x * x;
        z = x * x;
    }
}

これは、分解を見ると確認できます。

static {};
  Code:
   0:   iconst_3
   1:   putstatic       #5; //Field x:I
   4:   getstatic       #5; //Field x:I
   7:   getstatic       #5; //Field x:I
   10:  imul
   11:  putstatic       #3; //Field y:I
   14:  getstatic       #5; //Field x:I
   17:  getstatic       #5; //Field x:I
   20:  imul
   21:  putstatic       #6; //Field z:I
   24:  return

したがって、静的初期化子の途中に「return」を追加すると、zが計算されなくなります。

于 2010-04-09T12:21:09.387 に答える
11
  • プログラム フローは、return. System.exit(0)(あなたの例では、句を入れるとelse望ましい結果が得られます)

  • 本当に必要な場合は、コードを静的メソッドに移動して、初​​期化子から呼び出すことができます。

.

static {
    staticInit();
}

private static void staticInit() {
    if (yesNo) {
        System.out.println("Yes");
        return;
    }
    System.exit(0);
}

これは静的コンストラクターではなく、静的初期化子であることに注意してください。何も構築されません。

于 2010-04-09T11:57:47.107 に答える
2

静的初期化子に関するJSLから:

「静的初期化子がチェック済み例外 (§11.2) で突然完了できるのはコンパイル時エラーです (§14.1、§15.6)。静的初期化子が正常に完了できない場合はコンパイル時エラーです (§ 14.21)」。

突然の完了(とりわけ): 「値なしで戻る」、「指定された値で戻る」など。

したがって、静的初期化子の return ステートメントは「突然の完了」であり、コンパイル時エラーが発生します。

于 2010-04-09T12:09:29.340 に答える
1

あなたは何に戻るべきですか?静的初期化子には呼び出し元がいないため、私が見る限り、戻り値は意味がありません。静的イニシャライザは、クラスが初めてロードされるときに実行されます。

于 2010-04-09T11:56:04.500 に答える
0

静的初期化子のルールは、クラスのバイトコードがロードされた後、静的メソッドを実行する前、またはクラスから最初のオブジェクトをインスタンス化する前に、一度だけ実行されることを理解しています。JLSは、この初期化が完了していることを保証します。この保証が真であることを保証するために、JLSは、コードが突然終了することはできないことも指定しています(別の回答で明確に示されています)。

初期化せずにバイトコードをロードすることが可能であることに注意してください。Class.forName(String、boolean、ClassLoader)メソッドを参照してください。booleanパラメータがの場合、falseこれはクラスをロードしますが、初期化はしません。プログラマーは、初期化されていなくても、そのクラスに関する情報を発見するために、ある程度の反省を行うことができます。ただし、静的メソッドを呼び出すかインスタンスをインスタンス化してクラスを直接使用しようとすると、JVMは最初にクラスの初期化に進みます。

静的初期化子のいずれかが突然終了した場合(これは、で発生する可能性がありますRuntimeException)、クラスは無効な状態のままになります。初めて、JVMは(内部障害と見なされることを意味するExceptionInInitializeError通知)をスローします。Errorその時点から、クラスを使用することはできなくなります。静的メソッドを呼び出そうとしたり、オブジェクトをインスタンス化しようとすると、代わりにが取得されますNoClassDefFoundError

JVMを再起動せずにこの状況から回復する唯一の方法は、ClassLoadersを使用していて、クラスローダーを失敗したクラスに置き換え、別の環境(おそらく別のシステムプロパティ)でクラスまたは再初期化子を再構築できる場合ですが、プログラムはその場合このような状況に十分に備えてください。

于 2010-04-09T13:02:20.310 に答える
0

ステートメントを並べ替えて、よりシンプル/短くします。if/else の両方のブランチがリターンを必要とするような良いケースは決してありません。

static { 
    if (!yesNo) 
       System.exit(0); // silently exiting a program is a bad idea!"
    System.out.println("Yes"); 
} 
于 2010-04-10T07:02:20.430 に答える