#java #string #pass-by-reference
#java #строка #передача по ссылке
Вопрос:
В следующем коде
public class Test {
public static void main(String[] args){
int [] arr = new int[]{1,2};
String b=new String("abc");
f(b,arr);
System.out.println(b);
System.out.println(arr[0]);
}
public static void f(String b, int[] arr){
b ="de";
b=null;
arr[0] = 5;
}
}
Почему ссылочная переменная строки не ведет себя как ссылочная переменная массива?.
Я знаю, что string неизменяемы, поэтому операции над ними создают новую строку, но как насчет ссылок на strings и того, как ссылка b по-прежнему ссылается на старое значение, хотя оно было изменено, чтобы ссылаться на что-то другое в методе f().
Комментарии:
1. Ссылки на строки действительно ведут себя как другие ссылки. Попробуйте переименовать параметры
f
вx
иy
и сделать этоy = null;
внутриf
вместоarr[0]=5;
и, и вы, вероятно, поймете это.2. в вашем коде есть две разные переменные ‘b’, а не только одна.
Ответ №1:
Ссылки на объекты в Java передаются по значению. Присвоение просто изменяет значение, оно не изменяет исходную ссылку на объект.
В вашем примере arr[0]
изменено, но попробуйте arr=null
, и вы увидите, что это не имеет никакого эффекта после возврата метода.
Ответ №2:
Вызов метода в Java вызывается по значению, ну, по этому поводу ведутся долгие дебаты, но я думаю, что мы должны рассматривать с точки зрения языка реализации Java, которым является C / C . Ссылки на объекты просто указывают на объекты, а примитивы — это значения.. Всякий раз, когда вызывается метод, фактические аргументы копируются в формальные параметры. Следовательно, если вы измените указатель на ссылку на другой объект, это изменение не повлияет на исходный указатель, но если вы измените сам объект, вызывающая сторона также сможет увидеть изменения, потому что обе стороны ссылаются на один и тот же объект..
Ну, в вашем примере вы меняете ссылку на строку на null в вызываемом методе, но вы меняете объект, на который ссылается ссылка на массив.. Эти две операции не являются одинаковыми, поэтому они имеют разные последствия.. например, если вы измените код, как показано ниже, они будут выполнять семантически ту же операцию..
arr = null;
Ответ №3:
Вы не можете изменить аргумент для любого метода, однако вы можете сделать следующее.
public static void main(String... args) throws IOException {
String[] strings = {"Hello "};
addWorld(strings);
System.out.println("Using an array " Arrays.toString(strings));
StringBuilder text = new StringBuilder("Hello ");
addWorld(text);
System.out.println("Using a StringBuilder '" text "'");
}
private static void addWorld(String[] strings) {
for(int i=0;i<strings.length;i )
strings[i] = "World!";
strings = null; // doesn't do anything.
}
private static void addWorld(StringBuilder text) {
text.append("World !!");
text = null; // doesn't do anything.
}
С принтами
Using an array [Hello World!]
Using a StringBuilder 'Hello World !!'