我知道不可變意味着它是一個在實例化後不會改變狀態的對象。但是在這行代碼中,當數組值被聲明時,我看不到Final。 這個類是不可變的嗎?任何人都可以解釋如何找出答案。謝謝不可變的類如何識別
public class A {
private double[] values;
public double[] getValues(){
return values;
}
}
我知道不可變意味着它是一個在實例化後不會改變狀態的對象。但是在這行代碼中,當數組值被聲明時,我看不到Final。 這個類是不可變的嗎?任何人都可以解釋如何找出答案。謝謝不可變的類如何識別
public class A {
private double[] values;
public double[] getValues(){
return values;
}
}
是粘貼的代碼沒有任何最終關鍵字相關聯,並且沒有不可變的行爲。
嗯,我想帶出有關用Java編寫不變類的一些關鍵原則:
1)確保類不能被覆蓋 - 使課堂最後,或者使用靜態工廠,並保持構造私人
2.)使字段私有和最終 強制調用者在一個步驟中完全構造一個對象,而不是使用無參數構造函數與後續對setXXX方法的調用相結合(即避免使用Java Beans約定)
3.)不要提供任何我可以以任何方式改變對象狀態的方法 - 不僅僅是setXXX方法,而且可以改變狀態的任何方法
4.)如果類有任何可變的對象字段,那麼當它們通過時它們必須被防禦性複製班級和來電者之間
A a = new A();
a.getValues()[0] = 1.2;
只要值不爲空,就會工作。但是,您將無法將值重新分配給新陣列。那就是:a.getValues() = new double[5];
將不起作用。
該類不是不可變的,因爲我可以更改值,只是不重新分配它。
這是一個簡單的驗證。這些值被初始化爲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()返回的副本,可以避免陣列。
正如其他人寫這個對象被認爲是在其狀態可變。它永恆不變的是你無法交換它所擁有的數組。但是你可以改變數組的內容(getValues()[0] = 10;)。
要將其轉換爲不可變對象,必須使用List而不是數組。使用列表,您可以使用Collections'方法unmodifiableList將給定列表轉換爲可以保存到外部的版本。如果getValues()的調用方在不可修改的列表上使用add或remove,則會導致UnsupportedOpertionException,從而保持您的對象不被修改。
如果您需要堅持數組,您需要提供數組的副本(System.arraycopy)或克隆(clone())。
如果你無法改變它的屬性(包括從超類繼承的屬性,通常這個對象被認爲是不可變的,通常包括屬性值,但這是一個模糊的定義。
例如,如果您有一個包含指向文檔文件的File實例的類,並且此File實例無法更改,則該類將被視爲不可變(它提供的信息永遠不會更改),但指向的文檔每次都可以進行變異和改變。所以它實際上是一條模糊的線條(記住在你的例子中你不能改變數組,但是數組的內容)。
請參閱java中String類的實現。不可變類的最佳示例。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java –
'final'在這裏實際上沒有幫助;它返回不可變數組而沒有副本,這是問題。 –