7

さて、私が知る限り、私はfinal変数についてこれらのことを理解しています。

  1. 一度だけ割り当てる必要があります
  2. コンストラクターが完了する前に、すべてのfinal変数を初期化する必要があります

上記を使用しているので、以下がどのように機能しないのかわかりません。

public class FinalTest implements AnotherClass {

    private final Something something;
    private final otherthing;

    @Override
    public void setStuff(Something something) {
        this.something = something;
        this.otherthing = new SomeClass(something);
    }

    public FinalTest(Something something) {
        setStuff(something);
    }
}

ここでは、コンストラクターが完了する前に、final変数が設定されています。では、なぜコンパイラはそれに不満を言うのでしょうか?

4

5 に答える 5

18

メソッドがコンストラクターからのみ呼び出される必要はありません。コンストラクターの外部からも呼び出すことができます。また、将来的には同じコンストラクターに 2 回目の呼び出しが追加される可能性もあります。

今は使っていないかもしれませんが、Compiler はそれを確認できないため、許可しません。専門用語では、ありませんdefinite assignment

例: -次からクラスをインスタンス化するとしますmain: -

public static void main(String[] args) {
    FinalTest obj = new FinalTest(something);

    obj.setStuff(something); // There you go. This cannot be prevented. 
}

これに関する詳細な説明については、JLS - 明確な代入を参照してください。

于 2012-11-20T17:03:57.897 に答える
8

setStuff()オブジェクトの存続期間中に再度呼び出しを行うことは誰にも止められませんが、これは違法です。

finalフィールドは、1 回だけ実行されることが保証されているコード ブロック、つまりコンストラクターとインスタンス初期化子でのみ割り当てることができます。(または、static finalフィールドの場合は静的初期化子。)

詳細については、JLSを参照してください。

于 2012-11-20T17:03:58.237 に答える
3

コンパイラは、への唯一の呼び出しであることを認識していないためです

public void setStuff(Something something) {
    this.something = something;
    this.otherthing = new SomeClass(something);
}

コンストラクターから

于 2012-11-20T17:04:05.023 に答える
0

次の行は

private final otherthing;

何かのようなもの

private final Something otherthing;

あなたはクラスを欠席しています。

于 2012-11-20T17:04:22.680 に答える
0

補足:

@Override
public void setStuff(Something something) {
    this.something = something;
    this.otherthing = new SomeClass(something);
}

public FinalTest(Something something) {
    setStuff(something);
}

それは本当に悪い設計です。コンストラクターからオーバーライド可能なメソッドを呼び出さないでください。

于 2012-11-20T17:07:37.087 に答える