На самом деле, массивы не имеют значения, но указатели по отношению к объекту или примитивных типов данных. Если вы хотите получить подробный ответ, вы должны прочитать мой комментарий здесь: Java is NEVER pass-by-reference, right?...right? или здесь: In Java, what is a shallow copy?
Итак, как массивы являются указателями, что произойдет, если вы клонируете указатель с указателями в нем? Сначала указатели копируются для реального, но эти указатели указывают только на другой объект, который не клонирован. Поэтому, если вы хотите клонировать, я предлагаю не использовать массивы, а «более сложные» структуры данных: классы. Другая возможность никогда не будет хранить массив внутри массива ... например, я использую массивы только для контейнеров!
Но я не могу дать вам подробные сведения о многомерных дженериках Java, поскольку я никогда не занимаюсь ими не только из-за их возможной несогласованности, потому что они являются массивами (они все равно нарушают некоторые принципы OO и делают код уродливым) ,
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());
Результаты испытаний всегда будет выглядеть - независимо от того, если я использую = или клон():
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
Это не хорошее !!
Итак, каково обходное решение? Я предлагаю делать это в каждом классе структуры данных:
public class Foobar implements Serializable {
//any class variables...it doesn't matter which!
public Foobar() {
//do initialisation here...it doesn't matter what you do!
}
public Foobar copy(){
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Foobar foobar = (Foobar) ois.readObject();
return foobar;
}
catch(Exception e){
return null;
}
}
}
Таким образом, вы получите полную копию, реализовав только одна строка кода:
Foobar foo2 = foo1.copy(); //nice and easy!!
Преимущество этого решения: Это, как правило, достаточно реализовать интерфейс Serializable, чтобы сделать класс «копируемым». А если нет, вы можете решить любые проблемы, прочитав то, что написано в Serializable Javadoc!
Более того: не важно, какие объекты находятся в классе, который вы хотите сделать «копируемым», поэтому вам не нужно тратить больше времени на эту проблему. В конце концов, выше код является самым простым и быстрым решением, глубоко встроенным в Java с тех пор и использует только ОЗУ! (благодаря ByteArrayOutputStream)
Наслаждайтесь!
ОБНОВЛЕНИЕ: Обратите внимание, что вам нужно всего лишь использовать копию объекта, если требуется временный стек или если вы имеете дело с потоками (в общем случае, если вам нужны объекты, полностью независимые друг от друга). В противном случае вы не должны делать копии вообще! Также, если вы записываете некоторые данные в файл или сокет, вам не нужна копия. Более того, я предлагаю реализовать метод копирования только тогда, когда он действительно используется: для структур данных (модели). Поэтому будьте осторожны, используя этот мощный метод (иначе это может замедлить ваше приложение или даже заполнить хранилище Java VM, если вы делаете миллионы копий без каких-либо оснований, это может привести к тому, что stackoverflow действительно: o).
EDIT
я работал немного больше по этому вопросу. Поскольку я вдруг обнаружил, что существует общедоступный метод clone() «примитивных» массивов, которых нет в Java API! («пасхальное яйцо» из SUN для массивов типа String [] или int [] ;-)
И поскольку я использую реальные массивы в качестве основной структуры данных Foobar (а не ArrayLists!), Я могу изменить метод клонирования (из указанного класса), как это:
@Override
public Object clone(){
try{
Foobar foobar = (Foobar) super.clone();
String[] arrayClone = array.clone(); //who thought that this is possible?!
foobar.setArray(arrayClone);
return foobar;
}
catch(Exception e){
return null;
}
}
И теперь мы получаем этот результат прямо из коробки:
Instance: [Ljava.lang.String;@42e816 with value: 111
Instance: [Ljava.lang.String;@9304b1 with value: 111
Instance: [Ljava.lang.String;@42e816 with value: 999
Instance: [Ljava.lang.String;@9304b1 with value: 111
Проблема решена с «дважды вложенными " объектов !!! Как вы можете видеть, клоны имеют разные объекты независимо от оригинала ... поэтому foo1.equals (foo2)) будет ложным!
В методе клонирования класса необходимо также клонировать все его переменные класса! (Но если некоторые переменные класса являются массивами ArrayLists или более объемными массивами, даже это решение не будет работать!)
И, наконец, в чем проблема? Класс ArrayList не клонирует его массивы, он вызывает только метод copyOf в классе Array, что является вредным. Так никогда не используйте метод clone класса ArrayList и никогда не наследуйте какой-либо класс из ArrayList, потому что его метод clone не будет работать! (Он работает только в том случае, если класс ArrayList содержит только примитивы и никаких объектов ... в противном случае используйте простое решение ByteArray выше!).
Обратите внимание, что при использовании массивов большего размера, таких как Object [] [], вам всегда нужно реализовать решение ByteArray выше, они не могут быть клонированы! И если ваш массив огромен, это может занять некоторое время и понадобиться оперативная память.
Теперь вы специалист по клонированию! :-D
Многомерный массив в Java представляет собой массив указателей на массивы. Клон будет клонировать только первый массив. –
Итак, как я могу это сделать? Нужно ли создавать цикл, который копирует примитивный int из одного массива в другой? – AndreiBogdan
Вам нужно сделать цикл, который клонирует внутренние массивы. Или в классе Arrays может быть функция, чтобы сделать это - я не изучал этот класс с тех пор, как он был изобретен. –