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
.
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
已经改变了.
小智 10
对于最初的问题,
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Run Code Online (Sandbox Code Playgroud)
整数是不可变的,所以上面发生的是'a'已经改变为值6的新引用.初始值3在内存中没有引用(它没有被更改),所以它可以被垃圾收集.
如果这发生在String上,它将保留在池中(在PermGen空间中)比整数更长的时间,因为它期望有引用.
不可变并不意味着您不能更改变量的值。它只是意味着任何新的分配都会创建一个新对象(为其分配一个新的内存位置),然后将值分配给它。
要自己理解这一点,请在循环中执行 Integer 赋值(在循环外声明整数)并查看内存中的活动对象。
不可变对象不需要复制构造函数的原因是简单的常识。由于每次赋值都会创建一个新对象,从技术上讲,该语言已经创建了一个副本,因此您不必创建另一个副本。
归档时间: |
|
查看次数: |
62423 次 |
最近记录: |