I know this is probably very stupid, but a lot of places claim that the Integer class in Java is immutable, yet the following code:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Executes without any trouble giving the (expected) result 6. So effectively the value of a has changed. Doesn't that mean Integer is mutable? Secondary question and a little offtopic: "Immutable classes do not need copy constructors". Anyone care to explain why?
Immutable does not mean that a
can never equal another value. For example, String
is immutable too, but I can still do this:
String str = "hello";
// str equals "hello"
str = str + "world";
// now str equals "helloworld"
So what happened there? Since String
is immutable, clearly str
was not changed. But it now equals something different. This is because str
is now a completely newly instantiated object, just as your Integer
is. So the value of a
did not mutate, but it was replaced with a completely new object, i.e. new Integer(6)
.
a
is a "reference" to some Integer(3), your shorthand a+=b
really means do this:
a = new Integer(3 + 3)
So no, Integers are not mutable, but the variables that point to them are*.
*It's possible to have immutable variables, these are denoted by the keyword final
, which means that the reference may not change.
final Integer a = 3;
final Integer b = 3;
a += b; // compile error, the variable `a` is immutable, too.
You can determine that the object has changed using System.identityHashCode()
(A better way is to use plain ==
however its not as obvious that the reference rather than the value has changed)
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)));
prints
before a +=3; a=3 id=70f9f9d8
after a +=3; a=6 id=2b820dda
You can see the underlying "id" of the object a
refers to has changed.
To the initial question asked,
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Integer is immutable, so what has happened above is 'a' has changed to a new reference of value 6. The initial value 3 is left with no reference in the memory (it has not been changed), so it can be garbage collected.
If this happens to a String, it will keep in the pool (in PermGen space) for longer period than the Integers as it expects to have references.
Yes Integer is immutable.
A is a reference which points to an object. When you run a += 3, that reassigns A to reference a new Integer object, with a different value.
You never modified the original object, rather you pointed the reference to a different object.
Read about the difference between objects and references here.
Immutable does not mean that you cannot change value for a variable. It just means that any new assignment creates a new object ( assigns it a new memory location) and then the value gets assigned to it.
To understand this for yourself, perform Integer assignment in a loop ( with integer declared outside the loop ) and look at the live objects in memory.
The reason why copy constructor is not needed for immutable objects is simple common sense. Since each assignment creates a new object, the language technically creates a copy already, so you do not have to create another copy.
"Immutable classes do not need copy constructors". Anyone care to explain why?
The reason is that there is rarely any need to copy (or even any point in copying) an instance of a immutable class. The copy of the object should be "the same as" the original, and if it is the same, there should be no need to create it.
There are some underlying assumptions though:
It assumes that your application does not place any meaning on the object identity of instances of the class.
It assumes that the class has overloaded
equals
andhashCode
so that a copy of an instance would be "the same as" the original ... according to these methods.
Either or both of those assumptions could be false, and that might warrant the addition of a copy constructor.
This is how I understand immutable
int a=3;
int b=a;
b=b+5;
System.out.println(a); //this returns 3
System.out.println(b); //this returns 8
If int could mutate, "a" would print 8 but it does not because it is immutable, thats why it is 3. Your example is just a new assignment.
I can make clear that Integer (and other of its creed like Float, Short etc) are immutable by simple sample code:
Sample Code
public class Test{
public static void main(String... args){
Integer i = 100;
StringBuilder sb = new StringBuilder("Hi");
Test c = new Test();
c.doInteger(i);
c.doStringBuilder(sb);
System.out.println(sb.append(i)); //Expected result if Integer is mutable is Hi there 1000
}
private void doInteger(Integer i){
i=1000;
}
private void doStringBuilder(StringBuilder sb){
sb.append(" there");
}
}
Actual Result
The result comes to he Hi There 100 instead of expected result (in case of both sb and i being mutable objects) Hi There 1000
This shows the object created by i in main is not modified, whereas the sb is modified.
So StringBuilder demonstrated mutable behavior but not Integer.
So Integer is Immutable. Hence Proved
Another code without only Integer:
public class Test{
public static void main(String... args){
Integer i = 100;
Test c = new Test();
c.doInteger(i);
System.out.println(i); //Expected result is 1000 in case Integer is mutable
}
private void doInteger(Integer i){
i=1000;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1="Hi";
String s2=s1;
s1="Bye";
System.out.println(s2); //Hi (if String was mutable output would be: Bye)
System.out.println(s1); //Bye
Integer i=1000;
Integer i2=i;
i=5000;
System.out.println(i2); // 1000
System.out.println(i); // 5000
int j=1000;
int j2=j;
j=5000;
System.out.println(j2); // 1000
System.out.println(j); // 5000
char c='a';
char b=c;
c='d';
System.out.println(c); // d
System.out.println(b); // a
}
Output is :
Hi Bye 1000 5000 1000 5000 d a
So char is mutable , String Integer and int are immutable.
来源:https://stackoverflow.com/questions/5560176/is-integer-immutable