【问题标题】:Are Java wrapper classes really immutable?Java 包装类真的是不可变的吗?
【发布时间】:2011-05-06 06:59:12
【问题描述】:

Java Wrapper 类应该是不可变的。这意味着一旦创建了一个对象,例如,

Integer i = new Integer(5);

它的值不能改变。但是,做

i = 6;

完全有效。

那么,在这种情况下,不变性是什么意思? 这与自动装箱/拆箱有关吗? 如果是这样,有什么办法可以阻止编译器这样做?

谢谢

【问题讨论】:

    标签: java wrapper


    【解决方案1】:

    不可变意味着对象状态不能改变。在您的情况下,您没有更改对象new Integer(5),但您已更改引用i 以指向另一个对象。希望清楚:)

    【讨论】:

      【解决方案2】:

      i 是一个参考。您的代码将引用 i 更改为指向不同的、同样不可变的 Integer

      final Integer i = Integer.valueOf(5);
      

      可能更有用。

      【讨论】:

        【解决方案3】:

        i = 6 起作用的原因是自动装箱正在拦截并将其转换为i = new Integer(6)。因此,正如@Peter 所说,您现在指向一个新对象。

        【讨论】:

        • 几乎 - 它有效地将其转换为 Integer.valueOf(6)。有关更多信息,请参阅此内容:marxsoftware.blogspot.com/2010/08/…
        • 糟糕。我的坏 :-) 我实际上并没有费心去查它翻译的确切内容。
        【解决方案4】:

        编译器自动装箱原始值,这意味着

        Integer value = 6;
        

        将被编译为

        Integer value = Integer.valueOf(6);
        

        Integer.valueOf 将返回具有给定值的 Integer 实例。在您的情况下,i 现在将引用 Integer(6) 而不是 Integer(5),Integer(5) 对象本身不会改变。

        要查看此内容,您可以执行以下操作

        Integer i = new Integer(5);//assign new integer to i
        Integer b = i;//b refences same integer as i
        i = 6;//modify i
        System.out.println(i +"!="+b);
        

        这将打印6!=5,如果整数实例已被修改,它将打印6!=6

        澄清这只是为了说明对 Integer 的赋值如何只修改引用而不改变 Integer 实例本身。正如用户@KNU 指出的那样,它并没有证明或显示 Integer 的不变性,据我所知,不变性只是间接地由于其 API 中缺少修改方法以及 Integer.valueOf 返回的实例必须缓存一定范围。

        【讨论】:

        • 这是一篇关于原始/对象相等性的非常有趣的博客文章:marxsoftware.blogspot.com/2010/08/…
        • 这个例子并不能以任何方式证明Integer 的不变性。 “....如果整数实例已被修改,它将打印 6!=6 代替。”好的,在知道可变对象AtomicInteger 上重复上述测试怎么样?它仍然会打印6!=5,在上面的论点上泼水。
        • 注意:以上建议的测试需要使用i = new AtomicInteger(6);而不是i = 6;
        • @KNU 我添加了一个说明。
        • will be compiled as... 这件事对我来说真的很有启发性。直到现在我才关心它实际上是如何工作的。太棒了
        【解决方案5】:

        java 中的所有包装类都是不可变的。一旦创建了包装类对象,我们就无法更改其值,即无法更改包装在对象内部的值。因为包装类被用作原始数据类型的对象形式,并且如果它们是可变的,则在运行时会发生数据不一致。但是,您可以更改包装类引用变量以保存另一个对象。

        【讨论】:

          【解决方案6】:
          Integer i = new Integer(5);
          i++;                         // i  will become 6
          

          其中i++i = new Integer( i.intValue() + 1); 相同

          【讨论】:

          • 有趣的是,Java 编译器还推荐使用 ++ 吗? Swift 彻底摆脱了它 += 现在
          • @Greg Pricei 我很懒,所以 i++ 比 i+=1 短,比 i=i+1 凉
          • Duracell De Monaco 这是一本不错的读物,即使您没有接触过 swift。 :) stackoverflow.com/questions/35158422/…
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-10
          • 1970-01-01
          • 2019-08-20
          • 1970-01-01
          • 1970-01-01
          • 2011-09-04
          相关资源
          最近更新 更多