![](/img/trans.png)
[英]How can i make a class Immutable if it has a instance variable of java.lang.Object?
[英]Can a class (an instance of the class), containing Random object variable be immutable?
不變性的定義表明,在構造之后,對象的狀態(其數據)不能被改變。
這里提出了一個問題,在我看來,對象包含的狀態和數據是不同的東西。 也許狀態意味着通過getter提供的數據?
它並不意味着標記為私有且外部世界不可見的數據,這些數據確實可以改變而不會改變對象的狀態。
告訴我這是否正確:
final class Obj1 {
private final int i;
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1(int i) {
this.i = i;
}
public getI() {
j = rnd.nextInt(1000);
return i;
}
}
Obj1
一個實例是一個不可變對象。
final class Obj2 {
private final int i;
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1(int i) {
this.i = i;
}
public getI() {
return i;
}
public getJ() {
return j;
}
}
Obj2
的實例是一個可變或不可變的對象,為什么? 如果每次調用getter時我們在getJ體中得到下一個Random會怎么樣?
這樣的課程怎么樣? 可變/不可變,為什么?
final class Obj3 {
private final Random rnd = new Random();
private int j = rnd.nextInt(1000);
public Obj1() {
}
public getJ() {
return j;
}
}
這個如何? 可變/不可變,為什么?
final class Obj4 {
private final Random rnd = new Random();
public Obj1() {
}
public getRnd() {
return rnd.nextInt(1000);
}
}
關於不變性的一個重要觀點是,對象的可觀察狀態不得改變。
一個很好的例子是java.lang.String
,它經常被引用為不可變類的規范示例。 它有一個非final
字段,即hash
。 hash
保存哈希碼,但默認為0
。 哈希碼是在第一次調用hashCode()
並在該字段中緩存時延遲計算的。 這樣, String
對象的內部狀態可以改變,但是可觀察狀態永遠不會改變(因為hashCode()
總是返回相同的值,無論是計算還是只返回緩存的值)。
這意味着你提供的前三個樣本( Obj1
, Obj2
, Obj3
)是不可變的:它們沒有setter,並且在構造之后沒有其他任何東西可以改變它們的方法返回的值(最好將字段聲明為final
,但它不是不可變性的要求)。 另請注意,您也可以完全忽略這些類中的Random
字段,因為它無論如何都不會在構造之后使用。
我說最后一個樣本( Obj4
)肯定是可變的,因為你每次讀取它時都會改變狀態(即下一個getRnd()
調用返回的內容)(即每次調用getRnd()
)。
因此,回答標題中的問題:是的,如果Random
類的狀態在類本身的狀態下是不可觀察的,則引用Random
對象的類可以是不可變的。
如果引用被識別為識別而不是保持有問題的對象,則不可變對象保持甚至公開對任意類型對象的引用是完全合法的。 例如,將對象引用視為類似於VIN(車輛標識號 - 唯一標識車輛的字母數字字符串,至少是美國制造或進口的車輛),並想象維修車間可能保留一個它所服務的汽車的VIN列表。 汽車本身幾乎不會成為不可改變的物品,但是這個列表不能存放汽車 - 它會識別汽車。 人們無法看到VIN並且知道汽車在維修時的顏色是什么,但是當汽車進入商店時,可以使用VIN列表來確定汽車之前是否已經訪問過汽車。
好問題。 但這是術語的問題,而不變性更多的是關於如何使用對象。 不可變對象的好處:
如果它在構造之后改變它的狀態,即使它必須設置,我也不會將對象聲明為不可變的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.