Могу ли я изменить значение объекта String, переданное моему методу?
Я нашел следующий вопрос Является ли Java "pass-by-reference" " или "проход по значению" .
Я прочитал почти все, но не смог узнать, что делать, если мне нужен метод foo(-)
, чтобы изменить значение String
? (может быть, это тоже не ссылка), это не имеет значения для меня).
void foo(String errorText){
errorText="bla bla";
}
int main(){
String error="initial";
foo(error);
System.out.println(error);
}
Я хочу видеть bla bla
на консоли. Возможно ли это?
Ответы
Ответ 1
Вы не можете изменить значение errorText
в foo
, поскольку этот метод в настоящее время объявлен. Даже если вы передаете ссылку String errorText
в foo
, Java String
неизменяемы - вы не можете их изменить.
Однако вы можете использовать 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
) или просто вернуть строку.
Ответ 2
Использовать возвращаемое значение метода или создать класс-оболочку.
Вернуть ли это значение:
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());
}
Ответ 3
Да, вы можете изменить это с помощью отражений, но против правила.
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);
}
Ответ 4
Значения String неизменяемы - поэтому, как только вы получите значение, вы застряли с ним.
Ответ 5
Literal String
обрабатываются специально языком 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
неизменяемы; нет способа изменить их.
Ответ 6
Вы можете переназначить ссылку на String:
String foo(String err) {
return "bla blah"
}
error = foo(error);