I am using the OpenJDK Java compiler under Ubuntu. I wanted to convert a character array to a string and when that seemed to have ended up giving ambiguous results, I tried to write a toString
method of my own. In the process, I wrote a test program wherein (out of the fun of it) I tried to compile the following code.
class toString{
public static void main(String[] args){
string = "abc";
string = string + "bcd";
System.out.println(string);
}
}
Now, I know that String
objects in Java are immutable and the code should have in fact generated an error but to my surprise, it printed abcbcd
to the console. Does this mean that String
objects in Java are mutable or is there something wrong with the implementation of OpenJDK compiler in this case?
The code that you've posted above does not actually mutate any strings, though it looks like it does. The reason is that this line doesn't mutate the string:
string = string + "bcd";
Instead, what this does is:
string + "bcd"
.string
to refer to this new string.In other words, the actual concrete string objects themselves weren't changed, but the references to those strings were indeed modified. Immutability in Java usually means that objects cannot be modified, not the references to those objects.
An important detail that confuses a lot of new Java programmers is that the above line is often written as
string += "bcd";
which looks even more strongly as though it's concatenating bcd
onto the end of the string and thereby mutating it, even though it's equivalent to the above code and therefore doesn't cause any changes to the actual String
object (again, it works by creating a new String
object and changing what object the reference refers to.)
To see that what's going on here is that you're actually changing the reference and not the string it refers to, you can try rewriting the code to make string
final
, which prevents you from changing what object is referenced. If you do so, you'll find that the code no longer compiles. For example:
class toString{
public static void main(String[] args){
final String string = "abc";
string = string + "bcd"; // Error: can't change string!
System.out.println(string);
}
}
One final note - another common cause of grief for new Java programmers when using String
s is that String
has methods that appear to mutate the string but in actuality do not. For example, this code does not work correctly:
String s = "HELLO, WORLD!";
s.toLowerCase(); // Legal but incorrect
System.out.println(s); // Prints HELLO, WORLD!
Here, the call to s.toLowerCase()
does not actually convert the characters of the string to lower case, but instead produces a new string with the characters set to lower case. If you then rewrite the code as
String s = "HELLO, WORLD!";
s = s.toLowerCase(); // Legal and correct
System.out.println(s); // Prints hello, world!
Then the code will behave properly. Again, the key detail here is that the assignment to s
does not change any concrete String
object, but just adjusts what object s
refers to.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With