9
private static void changeString(String s) {
    s = new String("new string");
}

public static void main(String[] args) {
    String s = new String("old string");
    changeString(s);
    System.out.println(s); // expect "new string"
}

How could I make the output of "new string" happen with s as the only argument to method changeString?

thanks.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
Jichao
  • 40,341
  • 47
  • 125
  • 198

10 Answers10

11

In Java arguments are passed by value, object arguments pass a reference to the object, this means that you can change the reference of the argument, but that does not change the object you passed the reference to. You have two possibilities, return the new object (preferred) or pass reference to a container that can receive the new reference (collection, array, etc.) For example:

private static String changeStringAndReturn(String s) {
    return new String("new string");
}
private static void changeStringInArray(String[] s) {
    if (null != s && 0 < s.length) {
        s[0] = new String("new string");
    }
}
rsp
  • 23,135
  • 6
  • 55
  • 69
  • 5
    In Java, arguments are passed by value! – Tarquila Dec 22 '09 at 14:23
  • 2
    The funny thing is the code is correct but the "documentation" is misleading. I wonder if the same happens with his code? – OscarRyz Dec 22 '09 at 14:28
  • @rsp-could you correct your documentation, since it is the accepted answer – TStamper Dec 22 '09 at 15:34
  • Fixed that, the object reference is passed by value. – rsp Dec 22 '09 at 16:02
  • 1
    Do not do the array thing though. Yes it works, but it is a "hack" and you should really be using a return value. If you need to change multiple things either rethink the problem (usually you do not have to) or create a class and return that class. – TofuBeer Dec 22 '09 at 17:03
  • @Tofu, I did say returning the new value is the preferred method. The array is, as mentioned, an example of a container. Passing a Map would be a better alternative. And as we are nitpicking today, returning a class would not help :-) you mean to say define a data-holder object class and return a data-holder instance with multiple values. – rsp Dec 22 '09 at 19:47
6

References in Java are passed by value, so even if you modify the reference inside the function, changes won't be reflected back to the calling function because what you modify inside the function is just a copy of the original reference not the original reference itself.

But you can return the new string from your changeString method instead of trying to modify the reference there(inside the function) itself.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
4

Only if you make the function

private static void changeString(String[] s) {
    s[0] = new String("new string");
}

String are immutable, and Java has no concept of a 'pointer-to-a-reference' as a first class datatype. If you don't like the above, you can make a little class containing a single String field.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
2

You can, of course, return the new string from your changeString method instead of trying to change it in place.

Alternately, you can create an object that wraps or contains a string, and pass that in. The ChangeString method would change the string that was internal to your object, and the main method would still be holding a reference to that object.

Otherwise, you can't do this. String is immutable, and java always passes objects as a value that is a pointer to a particular object. Change where you're pointing, and you aren't referencing the same object anymore.

Jacob Mattison
  • 50,258
  • 9
  • 107
  • 126
2

Strings are immutable in Java and parameters are passed by value so you can't change them (there is not equivalent to ref in C#). You can pass in a StringBuilder and change it's contents just as easily.

rui
  • 11,015
  • 7
  • 46
  • 64
1

A: You can't, in Java object references are pass by value.

If you really need to, you can create a wrapper like this and use it the way you expected:

private static void changeString( _<String> str) {
     str.s("new string");
}

public static void main(String[] args) {
    _<String> s = new _<String>("old string");
    changeString(s);
    System.out.println(s); // prints "new string"
}
Community
  • 1
  • 1
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
1

I know this is old, but, just for posterity, most of this is mostly wrong.

In Java, non-primitives are passed by reference. Primitives (boxed and unboxed) are passed by value.

To directly answer OP, you're getting a reference to the actual String you passed. However, as @bmarguilies correctly pointed out - Strings are immutable in Java. Any assignment to a String creates a copy, then assigns the newly-assembled copy to the reference.

0

This is not possible in Java as everything in Java is passed by value. In this case where the argument is an object reference it is the value of the reference that is passed into the method, not the reference itself.

Mark
  • 28,783
  • 8
  • 63
  • 92
0

Java does not allow out parameters like C#, so you will not be able to achieve this as such.

Victor Nicollet
  • 24,361
  • 4
  • 58
  • 89
0

Its ugly but you could change the String to global static:

private static String s;

    private static void changeString(String t) {
        if(s.equals(t))
            s = new String("new string");
    }

    public static void main(String[] args) {
        s = new String("old string");
        changeString(s);
        System.out.println(s); // expect "new string"
    }
Ljdawson
  • 12,091
  • 11
  • 45
  • 60