Why are Strings seemingly passed by value when they are objects in Java?

What does this question mean? What should this code output?

String string = new String("unmodified");
change(string); //void method, sets string = "modified"
System.out.println(string);

With normal Java objects, it would print “modified”, but in this case, it will print “unmodified”. Why? You’d expect this behavior from primitive types like int and char, but String? Why; it’s a Java object?

It’s because Strings are immutable. We always hear this, but what does it mean?

Here’s how the steps of allocation memory allocation of the above code for a String, an immutable object.

  1. oldX holds a reference to location 0x0000, which stores “ab”.
  2. When change(String newX) method is called, newX is given a copy of the reference, 0x0000, which stores “ab” *
  3. Although newX = 0x0000, since strings are immutable, newX = “cd” in change(String newX) cannot translate to 0x0000 = “cd”. So newX = “cd” will instead create “cd” in a new memory location 0x0001 and do 0x0001 = “cd”.
  4. So newX holds a reference to 0x0001 while oldX still holds a reference to 0x0000.

Repeating in colloquial language: Originally, newX is 0x0000, right? So when we do newX = “cd”, we are essentially trying to do 0x0000 = “cd”. But we cannot force 0x0000 to be “cd” because strings are immutable and that memory location 0x0000 holds and will only hold “ab”. So when we do newX = “cd”, the system is FORCED to do 0x0001 = “cd” and make newX be 0x0001.

Here’s how the steps would be different if we used StringBuffer, a mutable object, instead of String, an immutable object.

  1. oldX holds a reference to location 0x0000, which stores “ab”.
  2. change(String newX) method is called where newX is given a copy of the reference, 0x0000.
    • So, newX holds a reference to location 0x0000, which stores “ab”
  3. Since StringBuffers are mutable, newX = “cd” in change(String newX) translates to 0x0000 = “cd”.
    • So newX holds a reference to 0x0001 while oldX still holds a reference to 0x0000.

*Java objects ALWAYS pass a copy of a reference to methods as Java does not have pass by reference. When you pass a String to a method, the value that’s passed is a reference to a String object, but you can’t modify that reference, and the underlying String object is immutable. So when you try to modify it, you will get a whole new reference that will point at the modification. (Instead of the old reference pointing to the modification).

Leave a Reply

Your email address will not be published. Required fields are marked *