整数是不可改变的

K.S*_*eff 93 java mutable immutability

我知道这可能非常愚蠢,但很多地方声称Java中的Integer类是不可变的,但是下面的代码:

Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Run Code Online (Sandbox Code Playgroud)

给出(预期)结果毫无困难地执行6.因此,a的值有效地改变了.这不意味着Integer是可变的吗?次要问题和一点offtopic:"不可变类不需要复制构造函数".有人在乎解释原因吗?

Tra*_*ebb 90

不可变并不意味着a永远不能等于另一个价值.例如,String也是不可变的,但我仍然可以这样做:

String str = "hello";
// str equals "hello"
str = str + "world";
// now str equals "helloworld"
Run Code Online (Sandbox Code Playgroud)

那发生了什么?由于str是不可改变的,显然str没有改变.但它现在等于不同的东西.这是因为Integer现在是一个完全新实例化的对象,就像你a的一样.所以价值new Integer(6)并没有变异,而是被一个全新的对象所取代,即a.

  • "这是因为str现在是一个完全新实例化的对象".或者更确切地说,str(一个varibale)_points_到一个新对象.对象本身不可变,但由于变量不是final,因此它可以指向不同的对象. (13认同)
  • 严格地说,*不需要*是*新*对象.Boxing使用`Integer.valueOf(int)`,该方法维护一个`Integer`对象的缓存.因此``=``对'Integer`变量的结果可能是以前存在的对象(或者它甚至可能是同一个对象......在'a + = 0`的情况下). (11认同)
  • 为什么 String 的 JavaDoc 明确表示它是不可变的,而 Integer 的 JavaDoc 却没有?这种差异就是我阅读这个问题的原因...... (3认同)

Mar*_*iot 48

a是某个整数(3)的"参考",你的速记a+=b真的意味着这样做:

a = new Integer(3 + 3)
Run Code Online (Sandbox Code Playgroud)

所以不,整数不可变,但指向它们的变量是*.

*可以使用不可变变量,这些变量由关键字表示final,这意味着引用可能不会更改.

final Integer a = 3;
final Integer b = 3;
a += b; // compile error, the variable `a` is immutable, too.
Run Code Online (Sandbox Code Playgroud)


Pet*_*rey 17

您可以确定对象已更改使用System.identityHashCode()(更好的方法是使用plain ==但不是显而易见的是引用而不是值已更改)

Integer a = 3;
System.out.println("before a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a)));
a += 3;
System.out.println("after a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a)));
Run Code Online (Sandbox Code Playgroud)

版画

before a +=3; a=3 id=70f9f9d8
after a +=3; a=6 id=2b820dda
Run Code Online (Sandbox Code Playgroud)

你可以看到对象的底层"id" a已经改变了.

  • System.identityHashCode() 是一个非常好的提示。谢谢你。 (2认同)

小智 10

对于最初的问题,

Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Run Code Online (Sandbox Code Playgroud)

整数是不可变的,所以上面发生的是'a'已经改变为值6的新引用.初始值3在内存中没有引用(它没有被更改),所以它可以被垃圾收集.

如果这发生在String上,它将保留在池中(在PermGen空间中)比整数更长的时间,因为它期望有引用.


And*_*ndy 8

是整数是不可变的.

A是指向对象的参考.当您运行+ = 3时,它会重新分配A以引用具有不同值的新Integer对象.

您从未修改过原始对象,而是将引用指向另一个对象.

这里阅读对象和引用之间的区别.


unc*_*ons 5

不可变并不意味着您不能更改变量的值。它只是意味着任何新的分配都会创建一个新对象(为其分配一个新的内存位置),然后将值分配给它。

要自己理解这一点,请在循环中执行 Integer 赋值(在循环外声明整数)并查看内存中的活动对象。

不可变对象不需要复制构造函数的原因是简单的常识。由于每次赋值都会创建一个新对象,从技术上讲,该语言已经创建了一个副本,因此您不必创建另一个副本。