Могу ли я изменить значение объекта String, переданное моему методу? - PullRequest
25 голосов
/ 21 ноября 2011

Я нашел следующий вопрос Является ли Java "передачей по ссылке" или "передачей по значению"? .

Я прочитал почти все из этого, но пока не смог узнать, что мне делать, если я хочу, чтобы метод foo(-) изменил значение моего String? (может быть или нет ссылки тоже, это не имеет значения для меня).

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

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

Я хочу видеть bla bla на консоли. Возможно ли это?

Ответы [ 6 ]

37 голосов
/ 21 ноября 2011

Вы не можете изменить значение errorText в foo, так как метод в настоящее время объявлен.Даже если вы передаете ссылку на строку errorText в foo, Java String s является неизменяемой - вы не можете их изменить.

Однако вы можете использовать StringBuffer (или StringBuilder).Эти классы можно редактировать в вашем методе foo.

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);
    }
}

Другими решениями является использование класса-оболочки (создайте класс для хранения вашей ссылки String и измените ссылку в foo) илипросто верните строку.

7 голосов
/ 21 ноября 2011

Либо используйте возвращаемое значение метода, либо создайте класс-оболочку.

Пусть будет возвращено значение:

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

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

Обернуть значение в объекте:

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());
}
4 голосов
/ 02 ноября 2016

Да, вы можете изменить это с помощью отражений, но это противоречит правилу.

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);
}
1 голос
/ 21 ноября 2011

Строковые значения неизменны - поэтому, как только вы получите значение, вы застряли с ним.

0 голосов
/ 21 ноября 2011

Вы можете переназначить ссылку на строку:

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

error = foo(error);
0 голосов
/ 21 ноября 2011

Литерал String s специально обрабатывается языком Java; ваш код примерно эквивалентен:

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);
}

Другими словами, вы просто указываете локальную ссылку errorText на другой объект String, который не влияет ни на что вне метода.

В более общем смысле, String s являются неизменными; нет способа их изменить.

...