繁体   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