На самом деле, Java передается по значению. Но у этого также есть "массивы по ссылке"! Вот почему многие думают, что Java является передачей по ссылке для объектов (по крайней мере, для массивов) и только передачей по значениям для примитивов.
Вот краткий тест:
String[] array = new String[10];
array[0] = "111";
ArrayList one = new ArrayList();
one.add(array);
ArrayList two = (ArrayList) one.clone(); //Alternate with: ArrayList two = one;
String[] stringarray1 = (String[]) one.get(0);
String[] stringarray2 = (String[]) two.get(0);
System.out.println("Array: "+one+" with value: "+stringarray1[0]);
System.out.println("Array: "+one+" with value: "+stringarray2[0]);
array[0] = "999";
String[] stringarray3 = (String[]) one.get(0);
String[] stringarray4 = (String[]) two.get(0);
System.out.println("Array: "+one+" with value: "+stringarray3[0]);
System.out.println("Array: "+two+" with value: "+stringarray4[0]);
Независимо от того, используете ли вы клон или используете =, System.out.print всегда будет выглядеть так:
Array: [[Ljava.lang.String;@addbf1] with value: 111
Array: [[Ljava.lang.String;@addbf1] with value: 111
Array: [[Ljava.lang.String;@addbf1] with value: 999
Array: [[Ljava.lang.String;@addbf1] with value: 999
Это доказывает, что клонирование и массивы являются вредной комбинацией, потому что массивы хранят только указатели! Мне все еще нужно проверить, верно ли это и для объектов без массивов ... потому что это будет означать, что Java всегда является "хранилищем по ссылке" (а функция "клон" будет плохой шуткой для любых объектов. содержит массивы), в то время как только примитивы являются реальными значениями и не имеют ссылок!
И так как мы знаем о логике: хранилище по ссылке x передача по значению == "хранение по значению x передача по ссылке" (для объектов!),
в то время как мы уже знали со школы: хранение по значению x передача по значению (для примитивов)
Итак, все ли нам лгали наши учителя по программированию (даже в университете)? Возможно, но, по крайней мере, они не делали никаких логических ошибок ... так что это не было ложью, это было просто неправильно.
EDIT
Я написал тот же код, что и выше, с классом, сначала структура данных:
public class Foobar implements Cloneable {
String[] array;
public Foobar() {
this.array = new String[10];
}
public String getValue(){
return array[0];
}
public String[] getArray(){
return array;
}
public void setArray(String[] array){
this.array = array;
}
@Override
public Object clone(){
try{
Foobar foobar = (Foobar) super.clone();
foobar.setArray(array);
return foobar;
}
catch(Exception e){
return null;
}
}
}
Теперь контроллер:
String[] array = new String[10];
array[0] = "111";
Foobar foo1 = new Foobar();
foo1.setArray(array);
Foobar foo2 = foo1; //Alternation: Foobar foo2 = (Foobar) foo1.clone();
System.out.println("Instance: "+foo1.getArray()+" with value: "+foo1.getValue());
System.out.println("Instance: "+foo2.getArray()+" with value: "+foo2.getValue());
array[0] = "999";
System.out.println("Instance: "+foo1.getArray()+" with value: "+foo1.getValue());
System.out.println("Instance: "+foo2.getArray()+" with value: "+foo2.getValue());
Результаты теста всегда будут выглядеть так - независимо от того, буду ли я использовать = или clone ():
Instance: [Ljava.lang.String;@42e816 with value: 111
Instance: [Ljava.lang.String;@42e816 with value: 111
Instance: [Ljava.lang.String;@42e816 with value: 999
Instance: [Ljava.lang.String;@42e816 with value: 999
Теперь у меня в кармане «мастер-массив», с помощью которого я могу управлять всеми объектами сразу! (что на самом деле не очень хорошая вещь)
Мне всегда было неловко из-за массивов Java, но я не мог сказать, что это было. Теперь я это знаю и чувствую себя хорошо, поскольку с тех пор я использовал массивы только как контейнеры для объектов ... только для того, чтобы удивляться, насколько они важны в таких языках сценариев, как PHP!
Тем не менее, массивы Java отлично подходят для синхронизации между потоками, поскольку вы можете легко передавать их и по-прежнему получать доступ к общим значениям. Но программисты, работающие на PHP, C ++ или где-то еще, действительно могут испытывать некоторые проблемы с массивами Java. ; D
О, мне нравится эта статья: http://javadude.com/articles/passbyvalue.htm
ОБНОВЛЕНИЕ: Я нашел отличное решение для копирования любого объекта, содержащего массивы, см. Мой комментарий здесь: Ошибка при использовании Object.clone ()