Java Mutable和Immutable概念

时间:2016-08-12 00:05:20

标签: java immutability mutable

我们可以创建一个包含可变对象的Immutable对象吗?有可能吗? 请让我更清楚这一点。

提前致谢。

5 个答案:

答案 0 :(得分:2)

是的,我们可以。

java.lang.String

中的代码为例
/** The value is used for character storage. **/
private final char value[];

显然数组是可变的,因为我们可以轻松地改变它们的内容:

value[0] = '&';

但是String仍然是不可变的。也就是说,一旦创建,其内容将永远不会改变。这是怎么发生的?

因为即使value是可变的,也没有"常规" String用户修改它的方式:

  1. value被声明为private finalString本身就是final,意思是没有子类。
  2. 没有setter方法。也没有任何修改value的方法。
  3. 我们可以从char数组创建一个字符串,但char数组被复制到构造函数中,因此修改原始数组对新创建的字符串没有影响。
  4. 多个value个实例也可以共享String字段,但只要它没有泄露,就可以安全。
  5. 我们可以将字符串转换回char数组,但又是一个副本。
  6. 所以如果我们仔细关注design strategy,答案是肯定的。

答案 1 :(得分:1)

在Java中(据我所知,所有其他主流语言都带有const / final / readyonly / val等关键字)"不可变& #34; object可以包含对可变对象的引用。要更深入地了解不变性,请参阅this paper - 快速介绍的是,有非官方的Java扩展允许您指定例如不可变对象只能包含对不可变对象的引用,例如JavariJoe3OIGJ

答案 2 :(得分:0)

Java中的对象永远不会包含其他对象 - 不像在C或其他一些编程语言中那样。甚至所谓的“容器”类实际上只包含引用到其他对象。

不可变对象可以引用任何其他对象,可变或不可变。

您不能更改不可变对象引用的其他对象,但如果它们是可变的,您可以更改其他对象。

答案 3 :(得分:0)

编辑:这在某种程度上取决于“不可变”的含义。正如另一个人所指出的,有时“不可变”被定义为“浅”不变性的形式 - 即允许对可变对象的持续引用。我自己并不喜欢这个定义。有些人可能在这里不同意我(并且希望没有人会对不同意见的b / c进行投票),我认为将“不变性”定义为“没有任何形式的可变状态”会更清楚。

根据这个定义,你的问题的答案是** no *因为如果它引用了可变对象,它赋予它可变状态,这会使对象本身变得可变。

我认为在这一点上区分常量引用指针和不可变对象非常重要。例如,以下代码是对常量对象的常量引用:

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)引用可变对象的对象是否仍然可以被认为是不可变的取决于你对“不可变”的定义。在我看来它不能因为引用一个可变对象赋予它可变状态;最好将其描述为不可变的,这会令人困惑/误导。

答案 4 :(得分:-1)

我认为这是可能的。但是引用可变对象的变量的访问修饰符必须是最终的。