Why are Java wrapper classes immutable?

2019-01-21 23:32发布

I know the usual reasons that apply to general immutable classes, viz

  1. can not change as a side effect
  2. easy to reason about their state
  3. inherently thread safe
  4. no need to provide clone/copy constructor/factory copy method
  5. instance caching
  6. no need for defensive copies.

However, wrapper classes represent primitive types, and primitive types are mutable. So why aren't wrapper classes mutable?

9条回答
够拽才男人
2楼-- · 2019-01-21 23:44

However, wrapper classes represent primitive types, and primitive types (except String) are mutable.

No they're not (and String isn't a primitive). But since primitive types aren't objects anyway, they can't really be called mutable / immutable in the first place.

Regardless, the fact the wrapper classes are immutable is a design decision (a good one IMO.) Thye could have just has easily been made mutable, or mutable alternatives provided too (indeed several libraries provide this, and other languages do by default.)

查看更多
成全新的幸福
3楼-- · 2019-01-21 23:45

For your info: if you want mutable holder classes, you can use the Atomic* classes in the java.util.concurrent package, e.g. AtomicInteger, AtomicLong

查看更多
放荡不羁爱自由
4楼-- · 2019-01-21 23:46

There are mutable, thread safe wrappers as well for some types.

AtomicBoolean
AtomicInteger
AtomicIntegerArray
AtomicLong
AtomicLongArray
AtomicReference - can wrap a String.
AtomicReferenceArray

Plus some exotic wrappers

AtomicMarkableReference - A reference and boolean
AtomicStampedReference - A reference and int
查看更多
何必那么认真
5楼-- · 2019-01-21 23:47

The wrapper classes are immutable because it just makes no sense to be mutable.

Consider following code:

int n = 5;
n = 6;
Integer N = new Integer(n);

At first, it looks straightforward if you can change the value of N, just like you can change the value of n.

But actually N is not a wrapper to n, but a wrapper to 6! Look at the following line again:

Integer N = new Integer(n);

You are actually passing the value of n, which is 6, to N. And since Java is pass-by-value, you cannot pass n into N, to make N a wrapper to n.

So, if we did add a set method to the wrapper:

Integer N = new Integer(n);
N.setValue(7);
print(N); // ok, now it is 7
print(n); // oops, still 6!

The value of n will not be changed and that will be confusing!

Conclusion:

  1. wrapper classes are wrappers of values, not wrappers of the variables.

  2. it will be confusing if you did add a set method.

  3. if you know it is a wrapper of a value, you will no longer ask for a set method. For example, you will not do "6.setValue(7)".

  4. it's impossible to make a wrapper to a variable in Java.

查看更多
爱情/是我丢掉的垃圾
6楼-- · 2019-01-21 23:47

The primitive types are mutable, but they are not shareable - that is no two sections of code will ever be referring to the same int variable (they are always passed by value). So you can change your copy and no one else sees the change, and vice versa. As Phillip shows in his answer, that would not be the case with mutable wrapper classes. So my guess is that they had a choice when the wrapped the primitive data types between:

matching the fact that you can change the value of a primitive type,

versus

matching the fact that primitive types can be passed around and no changes by a user will be seen by any other user of the data.

And they chose the latter, which required immutability.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-01-22 00:03

However, wrapper classes represent primitive types, and primitive types (except String) are mutable.

Firstly, String isn't a primitive type.

Secondly, it makes no sense to talk about the primitive types being mutable. If you change the value of a variable like this:

int x = 5;
x = 6;

That's not changing the number 5 - it's changing the value of x.

While the wrapper types could have been made mutable, it would have been annoying to do so, in my view. I frequently use readonly collections of these types, and wouldn't want them to be changeable. Very occasionally I want a mutable equivalent, but in that case it's easy enough to come up with one, or use the Atomic* classes.

I find myself wishing that Date and Calendar were immutable far more often than I find myself wanting Integer to be mutable... (Of course I normally reach for Joda Time instead, but one of the benefits of Joda Time is immutability.)

查看更多
登录 后发表回答