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";

  1. Alex on 2013-9-25

    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)

  2. newbie on 2013-11-18

    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.

  3. Daniel Gurianov on 2014-5-22

    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.

  4. yqj2065 on 2014-10-1

    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.

  5. Zsolt Káli on 2015-1-6

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

  6. Don on 2015-2-12

    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.

  7. xbai on 2015-10-12

    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;

  8. AraGon EdoGawa on 2016-11-4

    “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!

  9. Arvind Allawadi on 2017-5-10

    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

Leave a comment