簡體   English   中英

Java可變和不可變概念

[英]Java Mutable and Immutable concepts

我們可以創建一個包含可變對象的不可變對象嗎? 有可能嗎? 請讓我對此更加清楚。

提前致謝。

我們可以。

java.lang.String的代碼為例:

/** The value is used for character storage. **/
private final char value[];

顯然,數組是可變的,因為我們可以像這樣輕松地更改其內容:

value[0] = '&';

但是String仍然是不變的。 也就是說,一旦創建,其內容將永遠不會改變。 怎么發生的?

因為即使value是可變的, String的用戶也沒有“常規”方式來修改它:

  1. value宣布為private final 而且String本身是final ,意味着沒有子類。
  2. 沒有設置方法。 也沒有任何修改value方法。
  3. 我們可以從char數組創建一個字符串,但是char數組會在構造函數內部復制,因此修改原始數組不會對新創建的字符串產生影響。
  4. value字段也可以由多個String實例共享,但是只要不泄漏就可以了。
  5. 我們可以將字符串轉換回char數組,但同樣可以將其復制。

因此,如果我們認真遵循設計策略 ,答案是肯定的。

在Java中(據我所知,其他所有主流語言都帶有const / final / readyonly / val etc關鍵字),“不可變”對象可以包含對可變對象的引用。 要更深入地了解不變性,請參閱本文 -快速了解一下 ,有非官方的Java擴展允許您指定例如不可變對象只能包含對不可變對象的引用,例如JavariJoe3OIGJ

Java中的對象從不真正包含其他對象-不像C或某些其他編程語言那樣。 甚至所謂的“容器”類實際上只包含對其他對象的引用

不可變的對象可以引用任何其他可變或不可變的對象。

您不能更改不可變對象所引用的其他對象,但是可以更改其他對象的可變對象。

編輯 :這在某種程度上取決於您所說的“不變”。 正如另一個人指出的那樣,有時將“不變”定義為“淺”不變性的一種形式,即允許對可變對象的不變引用。 我自己不喜歡這個定義。 這里有些人可能不同意我的觀點(希望沒有人會反對意見分歧),我認為將“不變性”定義為“沒有任何可變的狀態”更為明確。

在此定義下,您的問題的答案為“否”,因為如果它引用的可變對象具有可變的狀態,則該可變的對象本身就是可變的。

我認為在這一點上區分常量引用指針與不可變對象很重要 例如,以下代碼是對常量對象的常量引用:

private final string abc = "John";

請注意,您無法修改“ abc”的狀態(即該特定字符串始終為“ John”-您以后無法將其更改為“ Johnny”,則需要創建一個新字符串。此外,您也可以不能用新字符串替換“ John”(即變量“ abc”本身將始終引用該字符串)。

以下代碼是對不可變對象的可變引用:

public string abc = "John";

(順便說一句,我確實意識到您應該在此處使用屬性)。

如果您以后要執行以下操作:

abc = "Johnny";

您將被允許這樣做。 在這種情況下,您要更改變量“ abc”所引用的對象,而不是原始字符串。 只要存在,字符串“ John”將始終具有該值。

但是,請考慮以下對象:

public class Defg
{
    public int Count;

    public Defg(int Count)
    {
       this.Count = Count;
    }
}

顯然,這是一個可變的類(因為您可以更改“ Count”的值)。

您可以執行以下操作:

// Mutable reference to a mutable object. Note: "Count: 1" is a bit of C# syntax that just means that the "Count" parameter is set to 1. It's not strictly necessary here, I just added it for clarity.
public Defg Mutable = new Defg(Count: 1);

// Constant reference to a mutable object
public final Defg ConstReference = new Defg(Count: 1);

請注意,以下全部完全正確:

Mutable = new Defg(Count: 10);
Mutable.Count = 4;
ConstReference.Count = 3;

但是,您不能執行以下操作:

ConstReference = new Defg(Count: 3);

請特別注意,Defg 不可能是不可變的對象,因為可以更改其狀態。

總結一下:
a)完全可以使用對常量對象的可變引用或對可變對象的常量引用-對該對象的引用的可變性與對象本身是否可變無關, 反之亦然
b)引用可變對象的對象是否仍然可以視為不可變取決於您對“不可變”的定義。 在我看來,這不是因為引用可變對象會導致其可變狀態。 將其描述為不可變的充其量只能是令人困惑/誤導。

我認為這是可能的。 但是引用可變對象的變量的訪問修飾符必須是最終的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM