Вы путаете изменчивость / неизменность объекта с копированием эталонных значений.
На этих диаграммах [var/index]
является ссылочной переменной, а {{an Object}}
является объектом.
String abc[]={"abc"};
String def[]={};
[abc] ------> {{a String[1]}}
[0] --------------> {{a String "abc"}}
[def] ------> {{a String[0]}}
Теперь вы делаете def
ссылочную переменную, указывающую на тот же объект, что и abc
ссылочная переменная:
def=abc;
[abc] ------> {{a String[1]}}
/ [0] --------------> {{a String "abc"}}
/
[def] ---/ {{a String[0]}}
На этом этапе массив нулевой длины не имеет ссылок и должен быть сборщиком мусора. Мы можем сузить наше обсуждение до массива длины один. Обратите внимание, что String[]
является массивом ссылок. Следующей строкой вы изменили то, на что указывает единственный элемент массива длиной один.
def[0]=def[0]+"changed";
[abc] ------> {{a String[1]}}
/ [0] ---------\ {{a String "abc"}}
/ \
[def] ---/ \--> {{a String "abcchanged"}}
Обратите внимание, что {{a String "abc"}}
сам по себе не был мутирован. [abc]
и [def]
теперь указывают на один и тот же {{a String[1]}}
, который является изменяемым (то есть вы можете сделать элементы массива, которые являются ссылками на String
объекты, указывать на что угодно).
, чтобы предотвратить изменение abc
при изменении def
, мне нужно будет сделать def = abc.clone()
;
На самом деле, это не совсем точно. Давайте посмотрим, что произойдет, если вы clone()
массив ссылок на изменяемый тип StringBuilder
.
StringBuilder[] abc = new StringBuilder[] { new StringBuilder("Hello") };
StringBuilder[] def = abc.clone();
def[0].append(" world!");
System.out.println(abc[0]); // prints "Hello world!"
В этот раз я не буду делать для вас диаграммы, но вы легко можете нарисовать их на бумаге. Здесь происходит то, что, хотя clone()
создает второй {{a StringBuilder[1]}}
объект со своим собственным элементом (то есть def != abc
), этот элемент указывает на тот же объект {{a StringBuilder}}
(т.е. def[0] == abc[0]
).
Короче говоря:
- Неизменяемость означает, что объекты определенного типа не могут изменяться каким-либо значимым образом для внешних наблюдателей.
Integer
, String
и т. Д. Являются неизменными
- Обычно все типы значений должны быть
- Объекты массива изменчивы
- Это может быть массив ссылок на неизменяемые типы, но сам массив является изменяемым
- То есть вы можете установить эти ссылки на что угодно
- Также верно для массива примитивов
- Неизменяемый массив не будет практичным
- Ссылками на объекты можно делиться
- Если объект изменчив, мутация будет видна через все эти ссылки
Если вам нужно более глубокое понимание проблем, я рекомендую следующее: