2012-07-05 3 views
10

私は最終変数について別のquestionを見ていて、最終変数を初期化せずに宣言できます(blank final変数)。これを行うことが望ましい理由はありますか?それはいつ好都合ですか?ブランク最終変数を使用するのはいつ適切ですか?

+1

かなり決してありません。空白の決勝は何もしません。彼らは決して意味のある価値を決して持つことができない変数です。その塩の価値があるJavaコンパイラは、警告やエラーを表示します。 –

+1

これはコンストラクタで初期化するときに便利です(コンストラクタのパラメータに基づいて)。 – sshannin

+0

最終的に最終的なものです。しようとすると final int a = 2; a = 3; それはエラー –

答えて

25

これは不変オブジェクトを作成するのに便利です。

public class Bla { 
    private final Color color; 

    public Bla(Color c) {this.color = c}; 

} 

のBlaは不変である(色は最終的なものであるため、一度作成し、それを変更することはできません)。 しかし、さまざまな色でそれらを構築することによって、さまざまなBlasを作成することはできます。

たとえば、this questionも参照してください。

A:Java Language Specification 4.12.4をCF - "ブランク最終的には" コメントでいくつかの混乱を作成しているように思われ、Javaで非常に特別な意味を持っていることを追加するかもしれない価値が

EDIT

blank finalは宣言に初期化子がない最終変数です。

次に、その空白の最終変数をコンストラクタに割り当てる必要があります。

+2

そこには私が正しいと思っていましたあなたはこれをすることはできません。 :)私はこれを知らなかった。 +1 –

+0

簡潔で明瞭です。ありがとう! –

2

オブジェクトの計測に先立って値がわからない場合は、コンストラクタに値が割り当てられている必要があります。

これは、immutable objectsを作成する方法であり、ビルダーパターンで使用されます。

class Builder{ 
    final BuilderContext context; 

    private Builder(BuilderContext context){ 
     this.context=context; 
    }  

    public static Builder New(){ 
     return new Builder(new BuilderContext()); 
    } 
+1

コンパイラ_will_はメソッド名として 'new'を文句を言います。 –

+0

私はそれをNewに素早く入力しました。 –

+0

New()メソッドを静的宣言してはいけませんか? @ジョンケーン – piepi

0

あなたは(コンストラクタで例えば)後でそれを初期化するために、彼らにあなたが持っている

を初期化せずにfinal変数を宣言することができますので、それは文句を言わない空とどまることに気づきました。

4

classのfinalプロパティには、オブジェクトが作成される前に値が割り当てられている必要があります。したがって、それらに値を割り当てることができる最後のポイントはコンストラクタです。

これはよくimmutable objectsに使用されます。 Wikipedia

から

public class Foo { 

    private final Bar bar; 

    public Foo(Bar bar) { 
    this.bar = bar; 
    } 

    public Bar getBar() { 
    return new Bar(bar); 
} 
} 

What wiki says about it

Defensive copying.

+0

うん。これは、Wikipediaの引用によると、 "空白の最後"と呼ばれるものです。 –

+0

@LouisWasserman、私はwikiがそれを記述していることに気付かなかった。私はWikiに参考文献を追加しましたが、あなたの「空白の最後」は、Wikiが知識を得るのに最高の場所ではないことを示しています。 ;-)。 –

+0

待って、何? OPリンクにWikipediaのリンクが含まれているという質問に対する回答が受け入れられました.Wikipediaのリンクには、あなたの答えに同意する引用が含まれています。 –

0

のJava 1.1で導入されたブランク最終的には、その宣言の初期化子を欠いている最終的な変数です。空白のファイナルは1回のみ割り当てることができ、割り当てが発生すると割り当てを解除する必要があります。これを行うために、Javaコンパイラはフロー分析を実行して空白の最終変数へのすべての割り当てに対して、変数が割り当て前に確実に割り当て解除されていることを確認します。そうしないと、コンパイル時エラーが発生します。

一般に、Javaコンパイラでは、値が割り当てられ、一度値が割り当てられると、最後の変数は別の値に再割り当てされない限り、空白の最後が使用されないことが保証されます。

1

空白の最終変数は、コンストラクタのどこかに割り当てる必要があります。むしろ、構築例:あなたは、その割り当て例外をスローすることがありますが、最終的に宣言するフィールドが、を持っており、それが起こる場合は、行動を取ることができるようにしたいとき

public class Test { 
    final int sign; 
    public Test(String upDown) { 
     if (upDown.equals("up")) { 
      sign = +1; 
     } else { 
      sign = -1; 
     } 
    } 
} 
1

一つのケースが考えられます。

class A { 
    final URLConnection conn; 
    A(String url) { 
    try { 
     this.conn = new URL(url).openConnection(); 
    } catch (IOException | MalformedURLException e) { 
     // Maybe this isn't fatal, so just handle the Exception 
     // here and move on happily 
    } 
    } 
} 
1

メソッド内でブランクの最終変数を使用すると、変数を使用するすべてのコードパスがその変数を一度(または例外をスローする)ことを示すことができます。 Javaコンパイラは、空の最終変数が使用される前に割り当てられることを保証します。いくつかのメソッド内

例コード:

final Foo foo; 
    if (condition1()) { 
    foo = makeFoo(1); 
    } else if (condition2()) { 
    throw new BarException(); 
    } else { 
    foo = makeFoo(-1); 
    } 
    ... 
    blahBlahBlah(foo); 

空白のfinal変数を使用すると、コンパイラは、誰かがblahBlahBlah(FOO)を呼び出す前にFOOを割り当てることを保証コードの次のリーダーに指示します。

「空白末尾変数」について質問します。 "blank final fields"についての議論は異なる議論であり、それ自体が興味深い。