2013-10-17 37 views
0

我知道不可變意味着它是一個在實例化後不會改變狀態的對象。但是在這行代碼中,當數組值被聲明時,我看不到Final。 這個類是不可變的嗎?任何人都可以解釋如何找出答案。謝謝不可變的類如何識別

public class A { 
private double[] values; 
public double[] getValues(){ 
return values; 
} 
} 
+0

請參閱java中String類的實現。不可變類的最佳示例。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java –

+2

'final'在這裏實際上沒有幫助;它返回不可變數組而沒有副本,這是問題。 –

回答

0

是粘貼的代碼沒有任何最終關鍵字相關聯,並且沒有不可變的行爲。

嗯,我想帶出有關用Java編寫不變類的一些關鍵原則:

1)確保類不能被覆蓋 - 使課堂最後,或者使用靜態工廠,並保持構造私人

2.)使字段私有和最終 強制調用者在一個步驟中完全構造一個對象,而不是使用無參數構造函數與後續對setXXX方法的調用相結合(即避免使用Java Beans約定)

3.)不要提供任何我可以以任何方式改變對象狀態的方法 - 不僅僅是setXXX方法,而且可以改變狀態的任何方法

4.)如果類有任何可變的對象字段,那麼當它們通過時它們必須被防禦性複製班級和來電者之間

+0

您應該在公共類的屬性上使用什麼修飾符,以便可以從任何包中的類的子類訪問 屬性(或方法),但不能從其他類在不同包中訪問 ?這是默認的嗎? – Juan

+0

@Juan保護。默認修飾符允許同一包中的任何類訪問它。受保護的是子類。儘管在給你的帖子第二次閱讀後,它聽起來像是你想在這兩者之間進行某種混合...... – Cruncher

+1

@Cruncher - 「protected」允許任何包中的子類訪問_也可以被同一包中的任何代碼訪問。 –

0
A a = new A(); 
a.getValues()[0] = 1.2; 

只要值不爲空,就會工作。但是,您將無法將值重新分配給新陣列。那就是:a.getValues() = new double[5];將不起作用。

該類不是不可變的,因爲我可以更改值,只是不重新分配它。

0

這是一個簡單的驗證。這些值被初始化爲1,2。

使用吸氣劑和參考,一個是能夠改變的第一項內的值的陣列中創建對象後

public class A { 
    private double[] values; 

    public double[] getValues() { 
     return values; 
    } 

    public static void main(String[] args) { 
     A test = new A(); 
     test.values= new double[]{1, 2}; 

     double[] valuesref = test.getValues(); 
     valuesref[0] = 10; 

     for (int i = 0; i < test.values.length; i++) { 

      System.out.println(test.values[i]);  
     } 
    } 
} 

這可以如果的GetValues()返回的副本,可以避免陣列。

+0

這是一種欺騙,因爲'test.values ='不適用於其他任何類。但是我認爲這反過來說明了這點 – Cruncher

+0

對,沒有setter或非默認構造函數的類非常有限。只是想強調一下這樣的事實,即數組可以使用引用改變它們的值 – Ram

1

正如其他人寫這個對象被認爲是在其狀態可變。它永恆不變的是你無法交換它所擁有的數組。但是你可以改變數組的內容(getValues()[0] = 10;)。

要將其轉換爲不可變對象,必須使用List而不是數組。使用列表,您可以使用Collections'方法unmodifiableList將給定列表轉換爲可以保存到外部的版本。如果getValues()的調用方在不可修改的列表上使用add或remove,則會導致UnsupportedOpertionException,從而保持您的對象不被修改。

如果您需要堅持數組,您需要提供數組的副本(System.arraycopy)或克隆(clone())。

如果你無法改變它的屬性(包括從超類繼承的屬性,通常這個對象被認爲是不可變的,通常包括屬性值,但這是一個模糊的定義。

例如,如果您有一個包含指向文檔文件的File實例的類,並且此File實例無法更改,則該類將被視爲不可變(它提供的信息永遠不會更改),但指向的文檔每次都可以進行變異和改變。所以它實際上是一條模糊的線條(記住在你的例子中你不能改變數組,但是數組的內容)。