为什么不可变类Integer的值可以重置?

时间:2013-11-28 18:05:08

标签: java

我之前读过,包装类都是不可变的。不可变意味着价值无法改变。下面我尝试了这个简单的例子,它可以粘贴到任何main方法中。首先,我创建一个包含值为5的整数。不可变意味着它们不能被改变,所以为什么我可以将I设置为89.我认为这是因为它改变了(I)指向的地方,但我不确定为什么会这样。

在我的下一个小例子中,我创建了一个x的整数,如果我尝试更改它会抛出错误。在这种特定情况下,x似乎是不可变的,但在(i)变量的情况下则不是。

似乎我可以改变(i)的值每当我想这样实际上没有最终关键字的整数是不可变的?如果我可以设置为89然后对我来说这似乎可以改变变量。

我已阅读其他帖子,我仍然不确定为什么我可以更改为另一个变量。在编写代码时,声明基本类型的最佳方法是什么。为什么不一直使用包装类来创建变量。

int y = 5; 
Integer i = new Integer(y);
i = 89;
final Integer x = Integer.valueOf(5);

System.out.println("Integer:(i) " + i.intValue());
System.out.println("Integer:(i) " + i.byteValue());

System.out.println("Integer:(x) " + x.intValue());;
System.out.println("Integer:(x) " + x.byteValue());;

i = i - 5;

使用所有包装器类来声明变量:(这会比使用原始变量类型声明这些变量更好)

Integer a = new integer(MyNewValue);
Integer b = new integer(MyNewValue);
Integer c = new integer(MyNewValue);
Integer d = new integer(MyNewValue);
Float   fa = new integer(MyNewValue);

3 个答案:

答案 0 :(得分:2)

您正在混淆两件事:更改“对象”本身的值并更改引用指向的对象。说i = 89只是将变量i指向一个新对象;它不会更改Integer最初指向的i对象。

使用final的预先挂起的变量声明只是确保禁止重新分配,它决不会声明它所指向的对象的可变性/不可变性。也许偏离主题,但我个人认为文章Java is Pass-by-Value, Dammit!是一本很好的读物。

答案 1 :(得分:1)

当您致电i = 89;时,您不会更改存储在内存中的Integer对象的值。相反,您要为int分配值为89的全新i。所以不可改变的规则没有被打破。

请注意,i只是一个指向Integer的引用,而不是实际的Integer本身。

答案 2 :(得分:1)

是的,看起来整数正在变化,但第3行发生的一切都是由编译器转换为i = new Integer(89)。如果你想看,你可以做

Integer i1 = i;
i = 83;
println(i); \\ prints out the original value 5
println(i1); \\ prints out a new value, 83

当你声明某些东西为final时,你不能改变变量的定义,尽管你仍然可以改变它里面的任何东西。 JavaRanch has a very nice analogy to help

当你可以避免它时,你不应该使用包装器对象,因为它们比基元效率低一些并且占用一些额外的字节。