为什么Primitives的包装类没有setter?

时间:2010-07-21 11:14:15

标签: java wrapper setter primitive-types immutability

为什么Wrapper类(如Integer,Double等)没有内部原始值的setter,这是什么原因?

我问这个是因为这种功能会简化微积分,并使Java语言更灵活一些。

让我举几个例子。

1)我们采取以下示例:

Integer x = new Integer(5);
x++;

幕后的前一个代码是执行自动装箱。类似的东西:

int x_tmp = x.intValue();
x_tmp++;
x = new Integer(x_tmp); // Yes that's a new memory allocation

由于这个问题,在Wrapper上执行微积分比在普通原始类型上执行要慢。使用setter,可以更容易地增加内部值,而无需在堆上分配另一个对象。

2)另一个困扰我的问题是,在Java中编写交换函数是不可能的,就像我可以在C(使用指针)或C ++(指针或引用)中那样。

如果我写void swap(Integer x, Integer y)我无法访问内部值,因为我将无法交换这些值。

PS: 我的一个朋友建议我应该考虑更大的图景,并考虑并发性和类型不变性。

那你有解释吗? 谢谢!

4 个答案:

答案 0 :(得分:6)

通常不使用包装类,除非您需要将它们放入集合中。如果它们是可变的,那么如果在集合内部使用并且作为哈希表的键,则会产生问题。

集合和哈希表需要哈希值始终相同。

答案 1 :(得分:4)

1)使用setter,包装器类型是可变的。不变性在很多方面都是一件好事......线程,代码的一般可理解性等。我个人认为,例如CalendarDate是可变的,这是一种耻辱。

事实上,您对x++;的扩展并不十分正确 - 它使用Integer.valueOf 始终创建新值。例如:

Integer x = 5;
x++;
Integer y = 5;
y++;

// This prints true    
System.out.println(x == y); // Compare references

只有有限范围的Integer值被缓存(规范定义了必须的行为方式,但如果JRE希望这样做,则允许更宽的范围) ...但它确实意味着它不会总是创建一个新对象。

2)是的,Java没有通过引用传递。坦率地说,我很少发现这是一个问题。您经常需要交换变量值吗?

答案 2 :(得分:4)

缓存在-128到127范围内的整数需要不可变的整数。考虑以下代码:

Integer id = Integer.valueOf(1);  // a new Integer, cached in Integer class

// and somewhere else

Integer key = Integer.valueOf(1);  // returns the cached value

现在如果整数是可变的并且有一个setter而且有人做了

key.setValue(2);  // not legal Java code, just for demonstration

这也会改变id的价值,让很多人感到惊讶:

Integer one = Integer.valueOf(1);
if (one != 1)
   System.out.println("Surprise! I know, you expected `1`, but ...");

答案 3 :(得分:1)

在Java中,字符串和包装类被设计为不可变的,以避免意外更改数据。您可以查看以下文章以获取更多信息。

Why Strings and Wrapper classes are immutable in java?