Подтвердить что ты не робот

Clone(): ArrayList.clone() Я думал, что мелкая копия

ArrayList<Integer> a=new ArrayList<Integer>();
a.add(5);
ArrayList<Integer> b=(ArrayList<Integer>)a.clone();
a.add(6);
System.out.println(b.toString());

В приведенном выше фрагменте кода я думаю, что clone() делает мелкую копию. Таким образом, b и a должны указывать на одно и то же место памяти. Однако, когда я делаю b.toString(), ответ будет только 5. Почему 6 также не отображается, если clone() делает мелкую копию?

4b9b3361

Ответ 1

Неглубокая копия не означает, что они указывают на то же место в памяти. Это будет просто назначение: List b = a;.

Клонирование создает новый экземпляр, содержащий одни и те же элементы. Это означает, что у вас есть 2 разных списка, но их содержимое одинаковое. Если вы измените состояние объекта внутри первого списка, он изменится во втором списке. (Поскольку вы используете неизменяемый тип - Integer - вы не можете это наблюдать)

Однако вы не должны использовать clone(). Он отлично работает с коллекциями, но в целом он считается сломанным. Используйте конструкторы-копии - new ArrayList(originalList)

Ответ 2

Если бы это было так, как вы думали, то метод clone был бы совершенно бесполезен, потому что в этом случае следующие строки были бы эквивалентны:

ArrayList<Integer> b = (ArrayList<Integer>)a.clone();
ArrayList<Integer> b = a;

Клонирование - как в реальных сценариях - процесс создания двух объектов с точно такими же свойствами (во время операции клонирования).

И как сказал Божо - избегайте концепции Java clone(). Даже автор упомянул, что он сломан.

Этот вопрос и ответы на него весьма ценны и предоставляют ссылку на комментарии Джоша Блоха к его работе; -)

Ответ 3

Неверное клонирование - это стратегия клонирования по умолчанию, предоставляемая Object.clone(), о которой вы говорите. Метод clone() класса объектов создает новый экземпляр и копирует все поля объекта Cloneable в этот новый экземпляр (либо он является примитивным, либо ссылкой). Поэтому в случае ссылочных типов только исходные биты копируются в новый экземпляр, поэтому ссылочная переменная обоих объектов укажет на один и тот же объект. Пример, который мы видели выше, является примером неглубокого клонирования.

Глубокое клонирование. Как следует из названия, глубокое клонирование означает клонирование всего от одного объекта к другому объекту. Чтобы достичь этого, нам нужно обмануть наш метод clone(), чтобы обеспечить нашу собственную стратегию клонирования. Мы можем это сделать, реализуя интерфейс Cloneable и переопределяем метод clone() в каждом ссылочном типе, который мы имеем в нашей иерархии объектов, а затем вызываем super.clone() и эти методы clone() в нашем методе клонирования объектов.

Но если вы посмотрите на метод clone() ArrayList в исходном коде, вы увидите, что он внешне копирует v.elementData = Arrays.copyOf(elementData, size); после вызова super.clone(), что означает, что clone() из ArrayList глубоко копирует его содержимое

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

Чтобы узнать больше о клонировании и его типах, таких как глубокое клонирование и мелкое клонирование, прочитайте Клонирование Java и типы клонирования (мелкие и глубокие) в деталях с примером

Ответ 4

мы не можем выбрать динамически, в какой позиции мы хотим добавить строку, подобную этой

int r=k.nextInt();
Integer i6=new Integer(r);
System.out.println("Enter the address");
String p6=k.nextLine();
ar3.add(i6,p6);

не пропуская после чтения целое число

Ответ 5

Функция clone в Arraylist не такая же, как копирование одного arraylist в другой. Если мы используем clone(), он хранит копию оригинального arraylist, но если мы внесем какие-либо изменения в первоначальный arraylist после использования clone(), он будет не влияет на скопированного arraylist.. Например:

public static void main(String[] a) {

List list = new ArrayList();

list.add("A");

List list2 = ((List) ((ArrayList) list).clone());

System.out.println(list);
System.out.println(list2);

list.clear();

System.out.println(list);
System.out.println(list2);
}

Вывод: -

[А]

[А]

[]

[А]

Ответ 6

Это действительно мелкая копия, вот комментарий для клона, из исходного кода ArrayList

Возвращает неглубокую копию этого экземпляра ArrayList. (Сами элементы не копируются.)

Чтобы понять это, рассмотрим фрагмент в методе clone из ArrayList

v.elementData = Arrays.copyOf(elementData, size);

Как известно, когда мы назначаем объект переменной, JAVA не создает совершенно новую копию этот Объект. Вместо этого эта переменная становится другой ссылкой, указывающей на исходный объект.

Таким образом, elementData фактически сохраняют ссылку на объекты, помещенные в этот ArrayList. И клонировать просто скопируйте эти ссылки, никакие реплики объектов не будут созданы.

Конечно, вы можете удалить или добавить новую ссылку на клонированный ArrayList.

Однако модификация старых объектов в одном массиве ArrayList будет влиять на исходный ArrayList. Трудно сделать иллюстрацию с вашим примером, поскольку Integer неизменен.

Чтобы увидеть побочный эффект, вы можете определить настраиваемый измененный объект

class Person {
        private int a;

        public void setA(int a) {
            this.a = a;
        }
        public int getA() {
            return a;
        }
        @Override
        public String toString() {
            return String.valueOf(a);
        } 
   } 

Затем вы можете использовать следующий код для тестирования

        Person p1 = new Person();
        Person p2 = new Person();

        ArrayList<Person> tt = new ArrayList<Person>();
        tt.add(p1);
        tt.add(p2);

        ArrayList<Person> yy = (ArrayList<Person>) tt.clone();
        Person vv = yy.get(yy.indexOf(p2));
        vv.setA(12);
        yy.remove(p1);

        System.out.println("tt: " + tt);
        System.out.println("yy: " +yy);

Выход должен быть

tt: [0, 12]
 yy: [12]

Посмотрите на побочный эффект:)? Мы только изменяем элемент в yy, но он также отражается в tt.