views:

489

answers:

9

Consider the following example.

String str = new String();

str  = "Hello";
System.out.println(str);  //Prints Hello

str = "Help!";
System.out.println(str);  //Prints Help!

Now, in Java, String objects are immutable. Then how come the object 'str' can be assigned value "Help!". Isn't this contradicting the immutability of strings in java?? Can anybody please explain me the exact concept of immutability??

Edit:

Ok....I am now getting it....But just one final question....what about the following code..

String str = "Mississippi"; 
System.out.println(str); //Prints Mississippi 

str = str.replace("i", "!"); 
System.out.println(str); //Prints M!ss!ss!pp!

Does this mean that two objects are created again (Mississippi and M!ss!ss!pp!) and the reference str points to a different object after "replace()" method????

+13  A: 

The object that str references can change, but the actual String objects themselves cannot.

The String objects containing the string "Hello" and "Help!" cannot change their values, hence they are immutable.

The immutability of String objects does not mean that the references pointing to the object cannot change.

One way that one can prevent the str reference from changing is to declare it as final:

final String STR = "Hello";

Now, trying to assign another String to STR will cause a compile error.

coobird
But in this case, the String object is 'str' which first contains the value 'Hello' and then gets assigned new value 'Help!'. What exactlyt do you mean by "The String objects containing the string "Hello" and "Help!" cannot change their values, hence they are immutable."??? Pardon me if this is a silly question. But iv got to clear it...
Light_handle
have you perchance every tried to program in C? Just read the primer on pointers and you'll understand coobird's answer perfectly.
Ryan Fernandes
See...This is what I want to avoid...I know you are a great programmer...and I am just trying to learn java here...So if you can answer my question correctly then please answer it...
Light_handle
You're confusing references and objects - `str` isn't the "object" it's a reference to the object. If you have `String str = "Hello";` followed by `String anotherReference = str;` you don't have 2 String objects, you have one object (the literal "Hello") and 2 references to it (`str` and `anotherReference`).
Nate
+1  A: 

The string object that was first referenced by str was not altered, all that you did was make str refer to a new string object.

daveb
+3  A: 

The String will not change, the reference to it will. You are confusing immutability with the concept of final fields. If a field is declared as final, once it has been assigned, it cannot be reassigned.

akf
+2  A: 

Immutability implies that the value of an instantiated object cannot change, you can never turn "Hello" into "Help!".

The variable str is a reference to an object, when you assign a new value to str you aren't changing the value of the object it references, you are referencing a different object.

OedipusPrime
+2  A: 

Though java tries to ignore it, str is nothing more than a pointer. This means that when you first write str = "Hello";, you create an object that str points to. When you reassign str by writing str = "Help!";, a new object is created and the old "Hello" object gets garbage collected whenever java feels like it.

twolfe18
+6  A: 

str is not an object, it's a reference to an object. "Hello" and "Help!" are two distinct String objects. Thus, str points to a string. You can change what it points to, but not that which it points at.

Take this code, for example:

String s1 = "Hello";
String s2 = s1;
// s1 and s2 now point at the same string - "Hello"

Now, there is nothing1 we could do to s1 that would affect the value of s2. They refer to the same object - the string "Hello" - but that object is immutable and thus cannot be altered.

If we do something like this:

s1 = "Help!";
System.out.println(s2); // still prints "Hello"

Here we see the difference between mutating an object, and changing a reference. s2 still points to the same object as we initially set s1 to point to. Setting s1 to "Help!" only changes the reference, while the String object it originally referred to remains unchanged.

If strings were mutable, we could do something like this:

String s1 = "Hello";
String s2 = s1;
s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
System.out.println(s2); // Prints "Hallo"


''Edit to respond to OP's edit:** If you look at the source code for String.replace(char,char) (also available in src.zip in your JDK installation directory -- a pro tip is to look there whenever you wonder how something really works) you can see that what it does is the following:

  • If there is one or more occurrences of oldChar in the current string, make a copy of the current string where all occurrences of oldChar are replaced with newChar.
  • If the oldChar is not present in the current string, return the current string.

So yes, "Mississippi".replace('i', '!') creates a new String object. Again, the following holds:

String s1 = "Mississippi";
String s2 = s1;
s1 = s1.replace('i', '!');
System.out.println(s1); // Prints "M!ss!ss!pp!"
System.out.println(s2); // Prints "Mississippi"
System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects

Your homework for now is to see what the above code does if you change s1 = s1.replace('i', '!'); to s1 = s1.replace('Q', '!'); :)


1 Actually, it is possible to mutate strings (and other immutable objects). It requires reflection and is very, very dangerous and should never ever be used unless you're actually interested in destroying the program.

gustafc
+1 for the fictional method, it demonstrates the differnce between immutable object and others.
Zappi
Thanks gustafc for the correct examples and clear explanation....But can you just answer the edited part in the question please? That will make my understanding clear.
Light_handle
+2  A: 

Light_handle I recommend you take a read of Cup Size -- a story about variables and Pass-by-Value Please (Cup Size continued). This will help a lot when reading the posts above.

Have you read them? Yes. Good.

String str = new String();

This creates a new "remote control" called "str" and sets that to the value new String() (or "").

e.g. in memory this creates:

str --- > ""


str  = "Hello";

This then changes the remote control "str" but does not modify the original string "".

e.g. in memory this creates:

str -+   ""
     +-> "Hello"


str = "Help!";

This then changes the remote control "str" but does not modify the original string "" or the object that the remote control currently points to.

e.g. in memory this creates:

str -+   ""
     |   "Hello"
     +-> "Help!"
mlk
nice way to show reference changes.
Stroboskop
+1  A: 

regarding the replace part of your question, try this

String str = "Mississippi"; 
System.out.println(str); //Prints Mississippi 

String other = str.replace("i", "!"); 
System.out.println(str); //still prints Mississippi 
System.out.println(other);  // prints M!ss!ss!pp!

[]]

Carlos Heuberger
A: 

Please see here "Why String is immutable in Java"

Javin Paul