27

I found the following question Is Java "pass-by-reference" or "pass-by-value"?.

I read almost all of it, but could not find out yet what should I do if I want the foo(-) method, to change my String's value? (maybe or not reference too, it doesn't matter to me).

void foo(String errorText){ 
    errorText="bla bla";
}

int main(){ 
    String error="initial"; 
    foo(error); 
    System.out.println(error);
}

I want to see bla bla on the console. Is it possible?

Community
  • 1
  • 1
merveotesi
  • 2,095
  • 13
  • 53
  • 83

6 Answers6

42

You can't change the value of errorText in foo as the method is currently declared. Even though you are passing a reference of the String errorText into foo, Java Strings are immutable--you can't change them.

However, you could use a StringBuffer (or StringBuilder). These classes can be edited in your foo method.

public class Test {
    public static void foo(StringBuilder errorText){ 
        errorText.delete(0, errorText.length());
        errorText.append("bla bla");
    }

    public static void main(String[] args) { 
        StringBuilder error=new StringBuilder("initial");
        foo(error); 
        System.out.println(error);
    }
}

Other solutions are to use a wrapper class (create a class to hold your String reference, and change the reference in foo), or just return the string.

Jack Edmonds
  • 29,945
  • 17
  • 62
  • 77
7

Either use the return value of the method or create a wrapper class.

Have it return the value:

String foo(String errorText){ 
    return "bla bla";
}

int main(){ 
    String error="initial"; 
    error = foo(error); 
    System.out.println(error);
}

Wrap the value in an object:

class StringWrapper {
    private String string;
    public StringWrapper(String s) {
        this.string = s;
    }
    public String getString() {
        return this.string;
    }
    public void setString(String s) {
        this.string = s;
    }
}

void foo(StringWrapper errorText){ 
    errorText.setString("bla bla");
}

int main(){ 
    StringWrapper error=new StringWrapper("initial"); 
    foo(error); 
    System.out.println(error.getString());
}
Erick Robertson
  • 30,990
  • 12
  • 68
  • 98
4

Yes you can change this with help of reflections but its against rule.

void foo(String errorText) {
    try {
        final Class<String> type = String.class;
        final java.lang.reflect.Field valueField = type.getDeclaredField("value");
        valueField.setAccessible(true);
        valueField.set(errorText, "bla bla".toCharArray());
    } catch (Exception e) {
    }

}

public static void main(String[] args) {
    String error = new String("initial");
    foo(error);
    System.out.println(error);
}
Saurabh Khare
  • 1,097
  • 12
  • 24
1

String values are immutable -- so once you get a value, you're stuck with it.

ryebr3ad
  • 1,200
  • 3
  • 11
  • 20
0

Literal Strings are treated specially by the Java language; your code is roughly equivalent to:

void foo(String errorText){ // at this point, errorText refers to the original string
    errorText=new String("bla bla"); // now it refers to a new string
}

int main(){ 
    String error=new String("initial"); // error is a reference to the original string
    foo(error); // pass a *copy* of the reference
    System.out.println(error);
}

In other words, you're just pointing the local reference errorText at a different String object, which affects nothing outside the method.

More generally, though, Strings are immutable; there's no way to modify them.

Oliver Charlesworth
  • 260,367
  • 30
  • 546
  • 667
0

You can reassign the String reference:

String foo(String err) {
  return "bla blah"
}

error = foo(error);
sudocode
  • 15,997
  • 40
  • 59