4

First, I know that strings in java are immutable.

I have a question about String immutability:

public static void stringReplace (String text) 
{
    text = text.replace ('j' , 'c'); /* Line 5 */
} 
public static void bufferReplace (StringBuffer text) 
{ 
    text = text.append ("c");  /* Line 9 */
} 
public static void main (String args[]) 
{ 
    String textString = new String ("java"); 
    StringBuffer textBuffer = new StringBuffer ("java"); /* Line 14 */
    stringReplace(textString); 
    bufferReplace(textBuffer); 
    System.out.println (textString + textBuffer); //Prints javajavac
} 

But if we write the following:

public static void bufferReplace (StringBuffer text) 
{ 
    text = text.append ("c");  /* Line 9 */
} 
public static void main (String args[]) 
{ 
    String textString = new String ("java"); 
    StringBuffer textBuffer = new StringBuffer ("java"); /* Line 14 */
    textString = textString.replace ('j' , 'c');
    bufferReplace(textBuffer); 
    System.out.println (textString + textBuffer); //Prints cavajavac
} 

The thing is I expected the first example would print the same as the second printed. the reason is when we pass textString to a function we actually pass a reference to textString. Now in the function's body another string was produced by text.replace ('j' , 'c') and we assigned a reference to that string to the string we passed in. In the second example I just assign a reference to the string produced by textString.replace ('j' , 'c'); to testString. Why there is so difference?

Follow by that reason, the results must be the same. What's wrong?

4
  • 3
    Btw. use StringBuilder instead of StringBuffer if you don't need it to be synchronized. Commented Oct 19, 2014 at 10:53
  • @jakub.petr Why it's so important? Commented Oct 19, 2014 at 10:54
  • 2
    @St.Antario Because StringBuffer is much slower than StringBuilder Commented Oct 19, 2014 at 10:55
  • From such a point of view any class/object may be considered immutable. Commented Oct 19, 2014 at 11:15

1 Answer 1

7

In the second example textString = textString.replace ('j' , 'c'); happens in your main method, so the textString variable is assigned a new String, and you see the new String's value when printing your output.

In the first example it doesn't happen, since the call to the stringReplace method can't change the String reference passed to it. Therefore, the output you see is as if you never called stringReplace(textString) at all.

This all boils down to Java being a pass by value language. You can't change an Object reference passed to a method, since that reference is being passed by value. If String wasn't immutable, you could change the String instance passed to the method by calling String methods that change its state (if such methods existed), but you still wouldn't be able to assign a new String reference to the method's parameter and see it reflected in the caller of the method.

Sign up to request clarification or add additional context in comments.

7 Comments

Interesting. It would be good if you provided a normative reference to JLS.
docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.1: When the method or constructor is invoked (§15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared type, before execution of the body of the method or constructor. Java is pass-by-value.
@St.Antario You are not mutating the StringBuffer reference passed to the method. If you tried to assign anew StringBuffer to the variable passed to the method, the result would be the same as with the method that accepts a String. The difference with StringBuffer is that you can mutate the object that the reference refers to inside the method.
Because text.append ("c") modifies the internal state of the StringBuffer, whereas text.replace ('j' , 'c') returns a copy of the text string, where j has been replaced by c.
No. A copy of the reference to the StringBuilder is made and passed to the method. So, assigning a new value to the reference doesn't change the original one, but since both references (the original and the copy) point to the same object, changing the state of the object in the method also affects it in the calling method: there is a single object involved.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.