2012-05-25 59 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使用final字段可以提高清晰度,因爲類可能很長。我不會在方法中使用final,因爲我試圖分解長方法。 –

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所說的將它重新綁定到不同的集合。

示例: 結合不可變列表實現,您可以獲得可以公開的安全成員。

例如: 當您依賴該引用不會更改時,您需要final。例如,在同步場景中就是這樣。

可能有更多的例子。如果你不打算改變參考,那麼宣佈成員最後是一種很好的風格。

5

使變量final確保在賦值後不能重新分配該對象引用。正如你所提到的,你仍然可以使用該列表方法進行更改。

如果您在使用的Collections.unmodifiableList結合final關鍵字,則GE你可能想實現的行爲,例如:

final List fixedList = Collections.unmodifiableList(someList); 

這與結果列表中指向的fixedList不能改變。然而,它仍然可以通過someList參考更改當心(所以一定要確保它超出這一範圍asignment後)。

1

我個人紀念我的課的收藏領域的final我類的用戶免於檢查無論是否爲空。這是有效的,因爲一旦該值已經分配給最終變量,它就永遠不會被重新分配給另一個值,包括null。

3

final在多線程下有很多後果。

  1. JMM明確定義了一個final字段的初始化完成是有保證的。

什麼是不明確的是:

  1. 編譯器是免費的跨內存屏障重新排序。
  2. 編譯器總是可以讀取緩存的副本。
1

要得到一個真正不可變的列表,您必須對列表內容進行深層複製。 UnmodifiableList只會使引用列表變得不可變。 現在製作List或數組的深層副本將隨着規模的增長而變得越來越難記憶。 您可以使用序列化/反序列化並將數組/列表的深層副本存儲到臨時文件中。由於成員變量必須是不變的,因此變換器不可用。 getter會將成員變量序列化爲一個文件,然後將其去極化以獲得深層副本。太陽能化具有進入對象樹深處的天生性質。儘管如此,這將確保以某些性能成本完全不變。

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類的實用方法Collections.unmodifaibleList(list)。