2012-05-25 6 views
50

ArrayList(または他のCollection)を最終的に作ることによって得られる利点と欠点は何ですか?私はまだ新しい要素をArrayListに追加し、要素を削除して更新することができます。しかし、それが最終的なものになる効果は何ですか?最終的なArrayListの意味は何ですか?

+1

配列がfinalとして宣言されている場合、配列に格納されているオブジェクトの状態を変更できます。変更を許可しないためには、変更不可能にする必要があります。 –

答えて

103

しかし、最終的な効果は何ですか?

この

はあなたが別の コレクション・インスタンスを指すように変数を再バインドすることができないことを意味しますスタイルの問題として

final List<Integer> list = new ArrayList<Integer>(); 
list = new ArrayList<Integer>(); // Since `list' is final, this won't compile 

、私は私のように変更するつもりはありませんほとんどの参照を宣言しますfinal

まだ新しい要素をArrayListに追加し、要素を削除して更新することができます。

ご希望の場合は、Collections.unmodifiableList()を使用して挿入、削除などを防ぐことができます。

final List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>(...)); 
+3

+1最終フィールドを使用すると、クラスがかなり長くなる可能性があるため、明瞭さが向上します。私は長い方法を打破しようとするほど、方法でファイナルを使用しません。 –

13

それはちょうどあなたがその参照を再割り当てすることができないことを意味します。以下のようなことをしようとすると、コンパイラのエラーが発生します。

final List<String> list = new ArrayList<String>(); 

list = new LinkedList<String>(); 
    ^
    Compiler error here 

本当に不変のリストが必要な場合は、Collections.unmodifiableList()メソッドを使用する必要があります。

7

たとえば、new ArrayListを使用してその参照を変更することはできません。

1

finalはjavaのキーワードまたは予約語で、 のメンバー変数、メソッド、クラスおよびローカル変数に適用できます。一度 最終参照を行うと、参照番号 を変更することはできません。 をJavaで再初期化しようとすると、コンパイラはこれを確認してコンパイルエラーを発生させます。

3

あなたが正当に観察したように、ArrayListでできることには影響しません.ArrayList自体はまだ変更可能です。あなたは参照を不変にしました。

しかし、変数の最終を作るには他の利点を持っている:

  • 一定のままと予想される場合には、変更される変数を防ぎます。これにより、将来のバグを防ぐことができます。
  • 変数を作成するfinalは、コンパイラが特定のパフォーマンスの最適化を行うのに役立ちます。

一般的に、あなたが変更できないものが多いほど、より良いものになります。だから、(たとえそれらが可変オブジェクトへの参照であっても)参照を最終的にすることは、一般的には良い考えです。

1

aixと異なるコレクションにリバインドすることはできません。

例: 不変リストの実装と併せて、あなたが公開できる安全なメンバーを取得します。

例: この参照に依存している場合は、最終的に変更する必要はありません。これは、例えば、同期シナリオに当てはまる。

さらに多くの例があります。あなたが参照をまったく変更しようとしない場合、最終的にメンバーを宣言するのは良いスタイルです。

5

変数finalを作成すると、そのオブジェクト参照が割り当てられた後でそのオブジェクト参照を再割り当てできなくなります。あなたが言及しているように、変更を加えるためにそのリストメソッドを使用することはできます。

あなたがCollections.unmodifiableListを使用してfinalキーワードを組み合わせる場合は、GE例えばあなたはおそらく達成しようとしている行動は、:

これは持っている
final List fixedList = Collections.unmodifiableList(someList); 

結果としてリストが指さことfixedListですることはできませんかわった。しかし、それでもsomeListの参照で変更することができます(したがって、この後に範囲外であることを確認してください)。

1

自分のクラスのコレクションフィールドをfinalと個人的にマークして、 nullであるかどうかに関係なくこれは、一度値が最終変数に割り当てられると、nullを含む別の値に決して再割り当てすることができないためです。

3

finalは、マルチスレッドの下で多くの結果をもたらします。

  1. JMMは明らかにfinalフィールドの初期化完了を保証しています。明確に定義されていない何

です:

  1. コンパイラは、メモリバリアを越え、それらを並べ替えることは自由です。
  2. コンパイラは常にキャッシュされたコピーを読み取ることができます。
1

本当に不変なリストを取得するには、リストの内容を詳細にコピーする必要があります。 UnmodifiableListは、参照のリストをやや不変にしかレンダリングしません。 リストまたは配列のディープコピーを作成すると、メモリサイズが増加すると難しくなります。 シリアル化/逆シリアル化を使用して、array/listのディープコピーを一時ファイルに格納することができます。メンバーは不変でなければならないので、セッターは利用できません。ゲッターはメンバ変数をファイルにシリアライズし、それをデシリアライズしてディープコピーを取得します。シリアライゼーションは、オブジェクトツリーの深みに入る固有の性質を持っています。これにより、パフォーマンスコストの点で完全な不変性が保証されます。

package com.home.immutable.serial; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 
import java.util.List; 

public final class ImmutableBySerial { 

    private final int num; 
    private final String str; 
    private final ArrayList<TestObjSerial> immutableList; 

    ImmutableBySerial(int num, String str, ArrayList<TestObjSerial> list){ 
     this.num = num; 
     this.str = str; 
     this.immutableList = getDeepCloned(list); 
    } 

    public int getNum(){ 
     return num; 
    } 

    public String getStr(){ 
     return str; 
    } 

    public ArrayList<TestObjSerial> getImmutableList(){ 
     return getDeepCloned(immutableList); 
    } 

    private ArrayList<TestObjSerial> getDeepCloned(ArrayList<TestObjSerial> list){ 
     FileOutputStream fos = null; 
     ObjectOutputStream oos = null; 
     FileInputStream fis = null; 
     ObjectInputStream ois = null; 
     ArrayList<TestObjSerial> clonedObj = null; 
     try { 
      fos = new FileOutputStream(new File("temp")); 
      oos = new ObjectOutputStream(fos); 
      oos.writeObject(list); 
      fis = new FileInputStream(new File("temp")); 
      ois = new ObjectInputStream(fis); 
      clonedObj = (ArrayList<TestObjSerial>)ois.readObject(); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       oos.close(); 
       fos.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     return clonedObj; 
    } 
} 
0

ここで達成しようとしているのは、リストを不変にすることです。しかし、リストの参照を最終的にマークすると、参照が他のリストオブジェクトを指すことができないことを意味します。

最終的な(変更不能な)ArrayListをコレクションクラスのユーティリティメソッドCollections.unmodifaibleList(list)の代わりに使用したい場合は、

関連する問題