Странность в уравненных Java-массивах: ссылки и указатели
Имея проблемы с пониманием того, что происходит в приведенном ниже коде. Поведение массивовc
а такжеd
это то, что я ожидал. Но что происходит сa
а такжеb
? (Я также пробовал это с нормальными скалярными переменными, и в обоих случаях ничего удивительного не происходит.)
Вывод копируется в комментарии по относительной влажности.
import java.util.Arrays;
public class ArraysParadox {
public static void main(String[] args) {
int[] c = {1, 2, 3};
int[] d = {6, 5, 4, 3};
System.out.print("c: ");
System.out.println(Arrays.toString(c)); // c: [1, 2, 3]
System.out.print("d: ");
System.out.println(Arrays.toString(d)); // d: [6, 5, 4, 3]
System.out.println("--- swap ---");
int[] tmp = c;
c = d;
d = tmp; // <----- Magic?
System.out.print("c' (=d): ");
System.out.println(Arrays.toString(c)); // c' (=d): [6, 5, 4, 3]
System.out.print("d' (=c): ");
System.out.println(Arrays.toString(d)); // d' (=c): [1, 2, 3]
System.out.println("--- c = 0 ---");
Arrays.fill(c, 0);
System.out.print("c (=0): ");
System.out.println(Arrays.toString(c)); // c (=0): [0, 0, 0, 0]
System.out.print("d (=c): ");
System.out.println(Arrays.toString(d)); // d (=c): [1, 2, 3]
System.out.println("--- d = 1 ---");
Arrays.fill(d, 1);
System.out.print("c (=d): ");
System.out.println(Arrays.toString(c)); // c (=d): [0, 0, 0, 0]
System.out.print("d (=1): ");
System.out.println(Arrays.toString(d)); // d (=1): [1, 1, 1]
System.out.println("================");
int[] a = {1, 2, 3};
int[] b = {6, 5, 4, 3};
System.out.print("a: ");
System.out.println(Arrays.toString(a)); // a: [1, 2, 3]
System.out.print("b: ");
System.out.println(Arrays.toString(b)); // b: [6, 5, 4, 3]
a = b;
System.out.print("a (=b): ");
System.out.println(Arrays.toString(a)); // a (=b): [6, 5, 4, 3]
System.out.println("--- α = 0 ---");
Arrays.fill(a, 0);
System.out.print("a (=0): ");
System.out.println(Arrays.toString(a)); // a (=0): [0, 0, 0, 0]
System.out.print("b (=a?): ");
System.out.println(Arrays.toString(b)); // b (=a?): [0, 0, 0, 0] ???
System.out.println("--- b = 1 ---");
Arrays.fill(b, 1);
System.out.print("b (=1): ");
System.out.println(Arrays.toString(b)); // b (=1): [1, 1, 1, 1]
System.out.print("a (=b?): ");
System.out.println(Arrays.toString(a)); // a (=b?): [1, 1, 1, 1]
}
}
Обменc
а такжеd
обозначает передачу по значению согласно этому сообщению: Ява - передача по значению, черт побери!. (Я также посмотрел наjava Передача массива по ссылке не работает?, но я не понимаю английского языка автора вопроса, и вызов метода затеняет пример.)
Обратите внимание, что со строкойd = tmp;
закомментировано,c
а такжеd
проявляет то же странное поведение, что иa
а такжеb
. Тем не менее, я не знаю, что с этим делать.
Кто-нибудь может объяснить, какa
а такжеb
оведение @ можно объяснить передачей по значению?
Оказывается, главная проблема в моем посте - не передача по значению, а наложение. Чтобы понять разницу между передачей по значению и указателями, я добавил следующий код в свой код и использовал его для (попытки) заменыc
а такжеd
(предложеностать ссылка на статью выше JavaDude).
static <T> void swap (T c, T d) {
T tmp = c;
c = d;
d = tmp;
}
В результате получается, чтоc
а такжеd
вернуться без изменений. Это сработало бы, если бы Java (например, C) передавала указатели наc
а такжеd
методу, но вместо этого он просто передает их значения, оставляя исходные переменные без изменений.
Меняетсяa = b
вa = b.clone();
илиa = Arrays.copyOf(b, b.length);
дает поведение, которое я ожидал. Этот код также работает:
int[] tmp = new int[b.length];
System.arraycopy( b, 0, tmp, 0, b.length );
a = tmp;
Относительное время описаноВо.