是以下類不變:的Java不變級規則
final class MyClass {
private final int[] array;
public MyClass(int[] array){
this.array = array;
}
}
是以下類不變:的Java不變級規則
final class MyClass {
private final int[] array;
public MyClass(int[] array){
this.array = array;
}
}
不,它不是因爲數組的元素仍然可以改變。
int[] v1 = new int[10];
MyClass v2 = new MyClass(v1);
v1[0] = 42; // mutation visible to MyClass1
沒有辦法讓數組不可變。這是沒有辦法讓任何客戶端代碼設置或刪除或添加項目數組。
這裏是一個真正的替代不變:(!這是我從讀書有效的Java保留 - 一個偉大的書)
private static class MyClass
{
private List<Integer> list;
private MyClass(final int[] array)
{
final List<Integer> tmplist = new ArrayList<Integer>(array.length);
for (int i : array)
{
tmplist.add(array[i]);
}
this.list = Collections.unmodifiableList(tmplist);
}
}
不,不可修改列表和asList創建視圖。因此,像JaredPar的答案一樣對數組進行外部更改將導致此版本的MyClass發生更改。 – ILMTitan 2010-06-29 18:42:44
'Arrays.asList(array)'也會返回一個'List
誰曾經低調不理解不可變的合同。 如果你返回一個可以改變的數據結構,不管它是否是某個支持數組的COPY,它仍然是__NOT__不可變的。克隆一些東西並返回一個可變的克隆__NOT__使一個類100%不可變,這也違反了最不驚人的原則。 asList不會__NOT__創建一個「視圖」,它將創建一個數組的__MUTABLE__副本作爲List。不可修改就是這樣,它返回一個不可修改的列表,因此不可變。 – 2010-06-30 14:33:34
我的兩個關於永恆規則美分:
並且不要實現'Serializable'。 – 2010-06-29 23:23:17
「不變性」是程序員和他自己之間的慣例。編譯器可能會或多或少地執行該約定。
如果一個類的實例在應用程序代碼執行的正常過程中沒有更改,則它們是「不可變的」。在某些情況下,我們知道他們不會更改,因爲代碼實際上禁止它;在其他情況下,這只是我們如何使用課程的一部分。例如,一個java.util.Date
實例是正式可變的(其上有一個setTime()
方法),但習慣上將它作爲不可變的處理;這只是應用範圍內的約定,不應調用Date.setTime()
方法。
至於其他注意事項:
String
被記錄爲不可變的(這就是Javadoc所說的)。但是,如果您查看源代碼,則會看到String
實例包含一個名爲hash
的私有字段,該字段可能會隨時間而改變:這是針對由hashCode()
返回的值的緩存。我們仍然認爲String
是不可變的,因爲hash
字段是內部優化,從外部看不到任何效果。final
的字段)。並不是說這是一個好主意:它可能會破壞使用所述實例的其他代碼段所使用的假設。正如我所說的,不變性是一個慣例:如果程序員想要自己戰鬥,那麼他可以,但是這會對生產力產生不利的副作用...MyClass
實例的不變性?這個問題沒有通用的答案。爲了使一個類不可變,你需要確保它上面的所有字段都是final的,並且這些字段的類型也是不可變的。
這可能是一個需要記住的痛苦,但有一個工具可以幫助你。
Pure4J提供了一個註釋@ImmutableValue
,您可以將它添加到接口或類中。
有一個maven插件可以在編譯時檢查您是否符合此後的不變性規則。
希望這會有所幫助。
如何?通過反射? – 2010-06-29 16:47:01
@Vivin添加了一個代碼示例 – JaredPar 2010-06-29 16:47:21
啊對!我一直忘記將參考文獻分配給私人會員。 – 2010-06-29 16:48:50