12

I know Integers are immutable in Java. But why it is designed this way?

I went through other answers before asking this question:

Is Integer Immutable

i++ still working for immutable Integer in Java?

Why are Java wrapper classes immutable?

But I couldn't find the use case which mandates the Integer to be immutable. Are there any technical reasons like there are for String?

  1. String is used as parameter in network connection, database URLs etc. It could easily be compromised if it was mutable.
  2. To support StringPool facility.
  3. To support class loading mechanism in which Strings are used as arguments. String being mutable results in a wrong class being loaded.

I understand there are wrappers like AtomicInteger for mutable.

UPDATE:

From the conversation, there is no universal reason that could mandate the Integers being immutable. However by doing immutable it provides some bonus as mentioned in the answers.

Such as this quote from Andrey

possibility to cache.

Others are reducing global state

easier multithreading

Community
  • 1
  • 1
Mani
  • 3,274
  • 2
  • 17
  • 27
  • `int i=23; Integer iObject=i;` if `Integer` is mutable then change `iObject` content should modify `i` variable, hence to avoid this they made it as Immutable. – snofty Jan 05 '17 at 18:16

5 Answers5

27

You won't find a mandatory reason why java.lang wrappers must be immutable. Simply because it's a design decision. They could have decided otherwise. The language designers had to choose between mutable and immutable. And they chose immutable. That's it.

There are some compelling (IMO) reasons though to make them immutable:

It's consistent with String. The same reasoning you provided for String to be immutable applies to Integer etc. as well (e.g. think of a port number in a property map). This generally applies to any mutable type.

Immutable types rule out a plethora of hard to find mistakes one can make where one involuntarily changed an objects member value by modifying the value obtained through a getter. It saves a lot of defensive copying when the type is immutable. The most infamous example is java.util.Date, which is generally a pain to use because it's mutable (API issues aside).

Also immutable types allow for the use of shared instances, like e.g. Integer does for commonly used values (see Integer.valueOf(int)).

Aaron Mansheim
  • 425
  • 3
  • 11
Durandal
  • 19,919
  • 4
  • 36
  • 70
  • 1
    Integer.valueOf(int) is always returning new Integer instance. it is not sharing like String Pool – Mani Apr 01 '14 at 18:39
  • 7
    @Mani You are mistaken, take a look at the javadoc and/or the source. – Durandal Apr 01 '14 at 18:41
  • @Mani since Integer is immutable it doesn't really matters does it use pooling or not. – Andrey Apr 01 '14 at 18:43
  • @Durandal - i may be wrong. but looking oversight at source , by default it is caching only -128 to 127 not all numbers. " Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS." - Correct me if i am wrong – Mani Apr 01 '14 at 18:46
  • @Mani: Yes, by default, but it couldn't do any caching at all if it were mutable. – Louis Wasserman Apr 01 '14 at 18:48
  • @LouisWasserman , I agreed , but to cache the numbers between -128 to 127 , do we need to pay extra Objects each time when we change the values ? – Mani Apr 01 '14 at 18:49
  • I'm not sure I follow. Given that you are caching the `Integer` values between -128 and 127, `Integer` must be immutable; you can only "change" an `Integer` value by changing the reference to be to another object, and if you are changing it to another value in that range, you are just changing the reference to another of the cached values. – Louis Wasserman Apr 01 '14 at 18:52
  • @LouisWasserman - I was trying to ask- just because to cache 256 numbers, Did the designers made the Integer as immutable and ask developers ? – Mani Apr 01 '14 at 19:00
  • 1
    @LouisWasserman immutability is what makes it possible to cache values. Don't switch cause and effect. – Andrey Apr 01 '14 at 19:01
  • @Mani designers did it immutable because it has several advantages, including possibility to cache. Others are reducing global state, easier multithreading. – Andrey Apr 01 '14 at 19:04
  • 2
    The "reason" (conjecture by me) why they chose immutable is that James Gosling wanted to avoid the common pitfalls of mutable types. Everything that came from the decision is a bonus/side effect. – Durandal Apr 01 '14 at 19:04
  • @Durandal I am pretty sure Gosling was aware of the bonuses that comes with immutability. – Andrey Apr 01 '14 at 19:08
5

Can the identity of the value 1 ever change? Can it become 2? No. That's why Integer and other numeric types are immutable. They're meant to model that identity.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • you should change the wording to primitive types – TTT Apr 01 '14 at 18:18
  • +1 for the case which i didn't thought about. but we are trying to set new value to object , which in turn creates new identity for the object like other Objects. for the argument if the hashcode of integer implemeted to returns the memory location of its being stored. the Integer Object identity is going to be same , but i will have luxury to modify the values right ?. - and if your point is 100% valid how it is possible in atomicInteger ( i understand it is atomic operation) but it is mutable and numeric value – Mani Apr 01 '14 at 18:21
  • @Mani The answer is in the javadoc. `Integer` states `The Integer class wraps a value of the primitive type int in an object.`, while `AtomicInteger` states `The Integer class wraps a value of the primitive type int in an object.` They serve different purposes. – Sotirios Delimanolis Apr 01 '14 at 18:26
  • @SotiriosDelimanolis . I could not able to follow. Integer states The Integer class wraps a value of the primitive type int in an object. I agreed that we are not arguing that. And the AtomicInteger states "value that may be updated atomically" . And again i do agreed that. Integer wraps an primitive int value which can be changed , so what is the problem to provide immutable – Mani Apr 01 '14 at 18:34
  • You're welcome. I copy-pasted that wrong, sorry. Maybe I should've quoted a different part of the javadoc: `An AtomicInteger is used in applications such as atomically incremented counters.` An `AtomicInteger` is specifically designed with mutability in mind. An `AtomicInteger` is not an `Integer`. – Sotirios Delimanolis Apr 01 '14 at 18:37
  • I actually never understood this argument. Identity of literal `1` can't indeed change but value of integer variable can change. So the difference between int and some object is that objects can't be stored, passed and copied by value in Java. And integers can't be truly passed by reference. It is not that you can't change value of integer. – Andrey Apr 01 '14 at 18:40
  • Yes. I agreed. And I dont have concerns about the AtomicInteger design. It is serves it purposes very well. While AtomicInteger changes the underlying primitive int value in atomic operation, why cant the Integer can change/allow to change the underlying primitive int – Mani Apr 01 '14 at 18:42
  • 2
    So `1` is `int`, not `Integer`. Java designers could have added mutational methods to `Integer` and it would be pretty mutable. So I think correct answer to question why `Integer` is immutable because the language was designed that way. – Andrey Apr 01 '14 at 18:42
  • @Andrey `Integer` is meant to be the reference type equivalent of `int`. Sure it was a design decision, but by that fact alone it has to be immutable. – Sotirios Delimanolis Apr 01 '14 at 18:45
  • @SotiriosDelimanolis I don't see any universal necessity for `Integer` to be immutable. I see advantages, yes, but it could easily be mutable. As most of the objects are. – Andrey Apr 01 '14 at 18:51
  • @Andrey You're right that there is no _universal_ necessity. What I'm saying is that for `Integer` to act like an `int`, it has to be immutable. `Integer` is an identity. – Sotirios Delimanolis Apr 01 '14 at 18:59
  • @SotiriosDelimanolis "for `Integer` to act like `int`" was also design decision. Necessity of `Integer` is that not everything is an object in Java. If you compare `Integer` to pointer to integer in C, in C you can easily modify the value to which pointer points. – Andrey Apr 01 '14 at 19:06
  • @SotiriosDelimanolis "Can the identity of the value 1 ever change? Can it become 2?" true but irrelevant, the value of X can change even if its an Integer, using your reasoning int's should be made 'final' too. I think the real reason is that Integer etc are just object wrappers around the corresponding primitive type not replacements for them. – Chris Milburn Apr 01 '17 at 17:23
  • @chris You're confusing types and variables. The `Integer` type was meant to model an integer value, which cannot change. The fact that a variable can be reassigned to a new value is what's _irrelevant_. – Sotirios Delimanolis Apr 03 '17 at 15:46
2

An integer literal (2, 3) is also immutable e.g. int var=3; It's the int variable (var on the left had side) that is mutable. The intention of Integer is "object as a value" (right hand side) rather than "object as a variable" (left hand side). Since Java uses references, variability (mutability) can be either in reference or in the object contents. The object reference (variable r in Integer r=2;) can be the variable aspect of this situation. As a result, variability is provided via a "variable reference" rather than "constant reference (i.e. no reference) to a variable primitive-typ content". It would be using a constant reference (constant r) and a variable content of the referred object.

They could have designed the class name Integer as a variable (non-immutable) but then eventually another class name would have been necessary for immutable (right-hand side value). So MutableInteger and ImmutableInteger both can be used in programs in one form or another. However, people happen to use the latter more often. So, early on Java developers decided to use the shorter name Integer for the latter (ImmutableInteger). There are various reasons why the latter turns out to be more useful and less error-prone that are explained well in other answers to this post. Both are possible and they both exist, just there is more demand for the latter.

Sohail Si
  • 2,750
  • 2
  • 22
  • 36
  • One of the various reasons is syntactic, and related to the keyword `final`. A constant `r` can be defined using the keyword `final` and this is only valid using an immutable integer class. If a mutable integer class is used then a final variable will change. – Sohail Si Apr 10 '15 at 13:03
  • 1
    So `int` is mutable and `Integer` is immutable? I couldn't find straight answer to this question even after going through several of these posts. – Arundale Ramanathan Sep 25 '20 at 10:57
0

In order for an object reference to encapsulate a value which is under the control of the thing that holds it, one of three conditions must apply:

  1. The class of the object must be immutable.

  2. The reference must identify an instance that will never be exposed to anything that might mutate it.

  3. The reference must never be shared with any object which isn't under the control of its holder, whether or not such a thing would mutate it.

Code which holds references of type Integer generally does so for the purpose of encapsulating integer values. Making Integer immutable makes it possible for classes to freely share references that are used to encapsulate value. Although there are times when a MutableInteger class would itself be useful [such a thing could probably be a little cleaner than a single-element int[] and more efficient than an AtomicInteger], one wouldn't pass a MutableInteger class to a method as a means of passing the number therein; one would instead pass it for the purpose of giving that method a place to store a number.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

I think immutability is a design choice that relates with garbage collection mechanism. At least, immutability helped the garbage collection to works more efficiently due to removal of several overhead mechanism that needs to be taken to guarantee the integrity of an object.

Earlier programming languages were invented in the era where the limitation of hardware constraints are pretty obvious (e.g. RAM and speed of processor and no runtime / bare to metal approach). In such environment, you need to be very careful about object instantiation, and, once it is instantiated, you should update it instead of throwing away for new values. In this respect, JAVA was one pioneer for popularizing the new approach with runtime and garbage collection - which - goes hand in hand with immutability.

Note that, more recent interpreters that use bytecodes such as Python (as opposed to, say, Perl) also use the immutability of integers and simple types.

From this source:

Programmers are often reluctant to employ immutable objects, because they worry about the cost of creating a new object as opposed to updating an object in place. The impact of object creation is often overestimated, and can be offset by some of the efficiencies associated with immutable objects. These include decreased overhead due to garbage collection, and the elimination of code needed to protect mutable objects from corruption.

Agung Dewandaru
  • 198
  • 1
  • 7