2

Javaでは、メソッドスコープ内で初期化されていない可能性のある変数を使用することはできません。クラススコープ内の初期化されていない変数は、クラスメソッドによって返される可能性があり、値のデフォルトはnullです。

なぜ2つの異なるスコープの異なる扱いですか?

public class TestClass {

    Integer i;
    Double d;

    public TestClass() {
        d = 1d;
    }

    public Double getD() {
        return d;
    }

    public Integer getI() {
        return i;
    }

//  public Integer getSomeInt() {
//      Integer i;
//      return i;
//  }

    public static void main(String[] args) {
        TestClass myClass = new TestClass();
        System.out.println(myClass.getI().getClass());
    }
}

これによりNullPointerExceptionが発生しiますが、getSomeInt()内に戻ると、「変数が初期化されていない可能性がある」ため、コンパイラエラーになります。

4

4 に答える 4

3

この背後にある理由は、Javaの静的コード分析の限界です。コンパイラは、スタックに割り当てられたローカル変数を初期化する前に読み取らないことを疑いの余地なく証明できます。これはヒープ割り当てメモリに対して行うことは不可能であるため、Javaは、ヒープ割り当てストレージへのポインタを公開する前に、すべてのヒープ割り当てストレージをゼロにすることを義務付けています。

このルールの結果は、ヒープに割り当てられたすべてのデフォルト値がゼロになることです(false、null、タイプの2進ゼロの値に関係なく)。

于 2012-07-23T12:25:35.353 に答える
2

メンバー変数にはデフォルト値があるため(初期化されていない場合)、そのため、Inullnullでメソッドを呼び出すと、次のようになります。NullPointerException

ローカル変数の場合、使用する前に初期化する必要があります。そうしないと、コンパイル時エラーになります。

ローカル変数は少し異なります。コンパイラは、初期化されていないローカル変数にデフォルト値を割り当てることはありません。宣言されている場所でローカル変数を初期化できない場合は、使用する前に必ず値を割り当ててください。初期化されていないローカル変数にアクセスすると、コンパイル時エラーが発生します。[....]

于 2012-07-23T12:13:36.007 に答える
1

とても簡単です。メンバー変数は自動的にデフォルト値に初期化されますが、ローカル変数は初期化されません。

あなたがするとき

public Integer getSomeInt() {
    Integer i;
    return i;
}

非表示 this.iにしてreturn i、(初期化されていない)ローカル変数を参照します。


では、なぜローカル変数は自動的に初期化されないのに、メンバー変数は自動的に初期化されるのでしょうか。

結局、これは言語の設計者だけが答えることができる質問ですが、推測しなければならないのは、割り当てられているすべてのメモリをゼロにする必要があるというパフォーマンスの問題によるものだと思います。ただし、オブジェクトに関しては、プログラマーにすべてのフィールドを明示的に初期化するように強制するのは面倒です。


JLS(4.12.3種類の変数)から:

クラス変数は、そのクラスまたはインターフェースが準備されたときに作成され(§12.3.2)、デフォルト値に初期化されます(§4.12.5)。

[...]

ローカル変数宣言ステートメントには、変数を初期化する式が含まれている場合があります。ただし、初期化式を持つローカル変数は、それを宣言するローカル変数宣言ステートメントが実行されるまで初期化されません。(明確な割り当ての規則(第16章、明確な割り当て)は、ローカル変数の値が初期化されるか、そうでなければ値が割り当てられる前に使用されることを防ぎます。)

于 2012-07-23T12:14:24.033 に答える
0

すべてのフィールドは、呼び出し後、他のsuper何よりも前に、コンストラクターで暗黙的に初期化されます。オブジェクト参照はに設定されnull、プリミティブ値はに設定されます0falseこの暗黙の初期化はメソッドでは実行されません。

于 2012-07-23T12:15:59.393 に答える