String is passed by “reference” in Java

This is a classic question of Java. Many similar questions have been asked on stackoverflow, and there are a lot of incorrect/incomplete answers. The question is simple if you don't think too much. But it could be very confusing, if you give more thought to it.

1. A code fragment that is interesting & confusing

public static void main(String[] args) {
	String x = new String("ab");
public static void change(String x) {
	x = "cd";

It prints "ab".

In C++, the code is as follows:

void change(string &x) {
    x = "cd";
int main(){
    string x = "ab";
    cout << x << endl;

it prints "cd".

2. Common confusing questions

x stores the reference which points to the "ab" string in the heap. So when x is passed as a parameter to the change() method, it still points to the "ab" in the heap like the following:


Because java is pass-by-value, the value of x is the reference to "ab". When the method change() gets invoked, it creates a new "cd" object, and x now is pointing to "cd" like the following:

string-pass-by-reference 2

It seems to be a pretty reasonable explanation. They are clear that Java is always pass-by-value. But what is wrong here?

3. What the code really does?

The explanation above has several mistakes. To understand this easily, it is a good idea to briefly walk though the whole process.

When the string "ab" is created, Java allocates the amount of memory required to store the string object. Then, the object is assigned to variable x, the variable is actually assigned a reference to the object. This reference is the address of the memory location where the object is stored.

The variable x contains a reference to the string object. x is not a reference itself! It is a variable that stores a reference(memory address).

Java is pass-by-value ONLY. When x is passed to the change() method, a copy of value of x (a reference) is passed. The method change() creates another object "cd" and it has a different reference. It is the variable x that changes its reference(to "cd"), not the reference itself.

The following diagram shows what it really does.
string-pass-by-reference 3

4. The wrong explanation

The problem raised from the first code fragment is nothing related with string immutability. Even if String is replaced with StringBuilder, the result is still the same. The key point is that variable stores the reference, but is not the reference itself!

5. Solution to this problem

If we really need to change the value of the object. First of all, the object should be changeable, e.g., StringBuilder. Secondly, we need to make sure that there is no new object created and assigned to the parameter variable, because Java is passing-by-value only.

public static void main(String[] args) {
	StringBuilder x = new StringBuilder("ab");
public static void change(StringBuilder x) {
	x.delete(0, 2).append("cd");
Category >> Basics >> Diagram >> Java >> Versus  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
String foo = "bar";
  • Ash

    If you will see java 8 Documentation, you will find this statement in String class, “Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared.” The statement clearly states that String is constant and immutable. That’s why you can share it between different functions without worrying about changing the value of String object. However, StringBuffer is mutable and thus the value of StringBuffer object will change if you change it in any other function. “A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls.” The explanation in 3rd and 4th are not agreeable.

  • Arvind Allawadi

    In solution #5, I am wondering for a long time, what did you do to make sure, “no new object created and assigned to the parameter variable?” Thanks

  • AraGon EdoGawa

    “Even if String is replaced with StringBuilder, the result is still the same.” Just tried it, the result is NOT the same! With StringBuilder, the changes are carried in the same object, there’s no “new” object being created like with String, so it’s because of immutability after all!

  • xbai

    You can modify the method like this instead of using StringBuilder which is not intuitive:

    public static void main(String[] args) {
    String x = new String("ab");
    x = change(x);


    public static String change(String x) {
    x = new String("cd");
    return x;

  • Don

    He basically said the same thing you mentioned in your second paragraph just that he explained it using the java pass-by-value concept which makes a lot more sense.

    Your suggested solution does not address the concern of not changing the reference to the original object while changing the state of the object!(i.e. We want to modify the “ab” string instance to an instance that is “cd” WITHOUT creating another “cd” string object in the string pool/heap. Hence the use of StringBuilder.) Changing x to an instance variable does nothing to prevent a new object from being created in the change() method.

  • Zsolt Káli

    That’s why using final keyword for the parameter(s) of a method is a good practice.

  • yqj2065

    I don’t with you.”x stores the reference which points to the “ab” string in the heap.”is incorrect.
    x stores “ab” which points to a string in the heap. “ab” itself is a reference of String object.

  • Daniel Gurianov

    I`ve never thought about it as pass-by-smth case. I used to think about this as scope of visibility case. Change method has its own X variable that can take any value you like without affecting outer X variable. I have no idea how pass-by-ref(value) is related to this example.

  • newbie

    I don’t know much about c or c++. But for java this post helped me a lot. For those of you who are still struggling to understand this concept refer to combined with this post should make things lot clear.

  • Alex

    I do not agree on the solution. I’m not an expert of C, and may be I’m wrong on the theorical side
    But the C code does not want to alter the contents of the object but the reference. So your solution (listing #3) makes no sense, since you are changing the inner state of the instance while the C want to change the referenced object

    imho a simple way to explain the reason for the code listing #1 for not working (as you expected, I mean) is that x variable is defined twice, once in row 2 and then in row 7. They are called with the same local name, but the scope is different, so they are different vars, and overwriting one does not overwrite the other. A proof of that is that you can change the type of X in the method parameter (ofc you cannot then call it with a String) and the compiler would not complain at all

    The solution to change X value is to have a common scope: if x is changed to be an instance variable, rather than a method scoped one, then listing #1 would produce the same effects of listing #2, even for immutable Strings (as soon as x is not marked final)