-1

I understand that on passing an array asn argument to a function, and making some change to the elements of the array inside the function, the changes will be reflected in the calling function as well, since arrays operates directly on memory (call by reference)

However, why is it that the same behavior does not apply to Strings? I was expecting Strings as well to work in the same way since a String is basically an array of characters.

Please see my code below. I pass in a String (character array) as well as an int array in to a function and make some changes in it. On printing these in main, I see that the String remains unaffected whereas the changes to the array are reflected.

import java.util.Arrays;

public class TestString
{
    public static void main(String[] args)
    {
        String s = "hello";
        int[] a  = new int[5];
        Arrays.fill(a, -1);

        fun(s,a);

        System.out.println(s);
        System.out.println(a[0]);
    }

    static void fun(String s, int[] a)
    {
        s = "world";
        a[0] = 99;
    }
}

Output

hello
99
tubby
  • 2,074
  • 3
  • 33
  • 55
  • 2
    [java is nowhere and never pass by reference.](https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CB4QFjAAahUKEwjqu_OfsMTHAhWGChoKHU3UCWg&url=http%3A%2F%2Fstackoverflow.com%2Fquestions%2F40480%2Fis-java-pass-by-reference-or-pass-by-value&ei=n3LcVarwCIaVaM2op8AG&usg=AFQjCNFUrSkfvIZmhZAHKQ8VJ2kffYjaMQ&cad=rja) – SomeJavaGuy Aug 25 '15 at 13:50
  • 6
    It's not an array of characters. It's an immutable object that contains an array of characters. – Kayaman Aug 25 '15 at 13:50

4 Answers4

5

Because Strings in java are immutable. Every "change" done to a string does not changes the original string but creates a new String object.

Januson
  • 4,533
  • 34
  • 42
  • 3
    There is no such thing as a "change done to a string". You can't change a string. That's what "immutable" means. When you say, "change done to a string," you are talking about changing a string _variable_. You know what you're talking about, and all of the experienced developers here know what you are talking about, but the noob does not. The noob is still learning the difference between objects and variables. Give him a little help. – Solomon Slow Aug 25 '15 at 14:13
5

First, the claim that a String is an array of characters is wrong. A String is an object, that has methods and is designed specifically not to allow any changes to be made in it.

Second, what you are doing is not changing some element of the parameter. You are changing the parameter variable. The parameter variable is basically a local variable, which receives a reference to the string that was passed as argument. Doing this:

s = "world";

Is not changing the string that was passed. It replaces contents of the local variable s with a new string. Since Java is always pass by value, this is not reflected outside of the method. It would be the same if you had:

a = new int[30];

inside the method. Outside of it you would still see the 5-element int[] that you passed inside.

a[0] = 99;

Is changing an element inside the array. So it looks at a, checks what it refers to, goes to that referred array, and changes its 0th element.

Since String is designed to be immutable, there is no way to do something similar in it. You can't do something like:

s.setCharacter(0,'a'); // This doesn't exist in Java

But you can do this with mutable objects. For example, if you had:

public static void manipulateStringBuilder( StringBuilder sb ) {
    sb.append(": manipulated");
    sb = new StringBuilder("New value assigned");
}

Then you could write something like:

StringBuilder sb = new StringBuilder("My string");
System.out.println(sb);
manipulateStringBuilder( sb );
System.out.println(sb);

And the output would be:

My string
My string: manipulated

This is because StringBuilder is a mutable object, combined with the fact that the value that you assigned to sb inside your method is never seen outside of it.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
2

It is because Strings are immutable. If you want to change the value of the String you should return it from the method and store it in the variable s again.

import java.util.Arrays;

public class TestString
{
    public static void main(String[] args)
    {
        String s = "hello";
        int[] a  = new int[5];
        Arrays.fill(a, -1);

        s = fun(s,a);

        System.out.println(s);
        System.out.println(a[0]);
    }

    static String fun(String s, int[] a)
    {
        s = "world";
        a[0] = 99;

        return s;
    }
}

I expect it will be helpful for you!

Francisco Romero
  • 12,787
  • 22
  • 92
  • 167
1

Java is not call by reference, but call by value, it is just that it passes references as values. More details here.

Strings are immutable, so you can't change the content (the char array) of a String, you can just replace it with a different one, i.e. you are changing the reference. But since the reference is passed by value, the change is not visible outside a method.

Actually you can change the content of String using reflection, which results in very interesting behavior. You use this only when you want to play a prank on a coworker.

Community
  • 1
  • 1
Jens Schauder
  • 77,657
  • 34
  • 181
  • 348