当前位置: 首页 > 知识库问答 >
问题:

为什么不可变类中的可变对象是可访问的?[副本]

晁文斌
2023-03-14

下面是一个不可变类的示例:

package com.immutable;

public final class ImmutableClass {

    private final int index;
    private final String tStr;
    private final ComplexObj cObj;

    public ImmutableClass(int i, String s, ComplexObj o){
        this.index = i;
        this.tStr  = s;

        ComplexObj cobj = new ComplexObj(o.someVar);
        this.cObj       = cobj;

    }

    public static void main(String[] args) {

        ImmutableClass icls = new ImmutableClass(5,"Hello World",new ComplexObj(100));

        System.out.println(icls.index + " | " + icls.tStr + " | " + icls.cObj.someVar);

        icls.cObj.someVar = 5;

        System.out.println("Second run :" + icls.index + " | " + icls.tStr + " | " + icls.cObj.someVar);

    }
}

下面是ComplexObj类的实现:

package com.immutable;

public class ComplexObj {

    int  someVar;

    public ComplexObj(int i){
        this.someVar = i;
    }
}

当我创建immutableclass实例时,我正在immutableclass的构造函数中对complexobj进行深度复制,但是我能够通过icls.cobj.somevar更新cobj的值,这种方法破坏了my类的不变性。我在这里做错了什么?

共有1个答案

微生景胜
2023-03-14

你的不可变类就像一个钛和混凝土的纪念碑。一旦创建,它几乎不会受到破坏。

你的纪念碑上写的是海滩上一个非常漂亮的沙堡的位置。

一个人期望他们充分享受您的纪念碑包括发现,开车到那里,并凝视沙城堡。

另一个人开车过来把城堡夷为平地。

第一个人现在觉得他们的经历被改变了。

第三个人决定就什么是不变的意思进行一场哲学辩论,并说纪念碑根本没有改变:沙堡的那个位置仍然在那里,没有改变。

第一个人和第三个人决定为此打一架。

你告诉我,谁是对的?第一个,还是第三个?

因为它和你的Java密码完全吻合。你就像第一个。谁说‘使一个类最终,每个字段最终,然后那个类的对象将是不可变的’就像第三个。

如果你想让纪念碑的体验不变,那么要么那个沙堡也需要是钛和混凝土的概念,这不是这个纪念碑的建造者可以做到的(你必须要求沙堡的建造者做到这一点),要么你就不需要把非不透水的东西的位置放在那个纪念碑上。

换句话说,如果您希望类是“经验”不可变的,就不要在类中包含非不可变类型的字段--也就是不要包含complexobj类型的字段,或者也使这些字段不可变,即编辑complexobj.java并例如使该字段final

 类似资料:
  • 问题内容: 为什么Redux中的对象是不可变的?我知道某些框架(例如Angular2)将使用onPush并可以利用不变性来比较视图状态以更快地呈现,但是我想知道是否还有其他原因,因为Redux与框架无关,但它在其自己的文档中提到要使用不变性(与框架无关)。 感谢任何反馈。 问题答案: Redux是一个小型库,将状态表示为(不可变的)对象。和 新状态 通过将当前状态传递给纯函数来创建全新的对象/应用

  • 问题内容: 就像标题所问的那样,Django伙计们为什么决定使用querydict来实现request.POST对象(当然,这又使整个事情变得不可变了?) 我知道你可以通过复制帖子数据来对其进行更改 但是为什么呢?当然,仅允许事物变得易变会更简单吗?还是由于其他原因使用它而可能导致问题? 问题答案: 这是一个谜,不是吗?在调查中,一些表面上似乎合理的理论是错误的: 这样POST对象就不必实现变异方

  • 问题内容: 为什么我不能执行以下操作: 我希望它能打印出来,因为我们用它覆盖了实例,但是它根本不做任何事情。甚至不会抛出错误。只是忽略分配。 我了解几乎没有任何人愿意这样做,但是您似乎做不到,这仍然很奇怪。 更新: 我现在知道 为什么 它不起作用,但是我仍然想知道是否有任何方法可以从实例中替换实例。 问题答案: 任何 简单的分配给 任何 的参数 任何 函数的行为确实是在Python以同样的方式:结

  • 本文向大家介绍Java 中的 String对象为什么是不可变的,包括了Java 中的 String对象为什么是不可变的的使用技巧和注意事项,需要的朋友参考一下 什么是不可变对象? String对象是不可变的,但这仅意味着你无法通过调用它的公有方法来改变它的值。 众所周知, 在Java中, String类是不可变的。那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再

  • 我是java编程的新手。而且我不明白为什么string对象在Java中是不可变的。

  • 问题内容: 我正在努力使可变对象与不可变对象有关。使用可变对象会带来很多负面影响(例如,从方法中返回字符串数组),但是我很难理解它的负面影响。使用可变对象的最佳实践是什么?您是否应尽可能避免使用它们? 问题答案: 好吧,这有几个方面。 没有参考身份的可变对象会在奇数时间导致错误。例如,考虑使用基于值的方法的 : 当实例用作键时,实例在映射中“丢失”,因为实例和相等性基于可变值。这些值在映射之外更改