Java: мелкое копирование (клонирование) у меня не работает? - PullRequest
1 голос
/ 26 апреля 2020

Согласно определению:

Мелкая копия - это копия, в которой мы копируем только значения полей из одного объекта в другой. Это разные объекты, но проблема в том, что когда мы изменяем какие-либо свойства исходного адреса, это также влияет на адрес shallowCopy.

Я попытался проверить, являются ли значения объекта 1 и объекта 2 становится таким же, поэтому попробовал следующее и не смог сделать это.

public class TestClone implements Cloneable {
    private String a;

    public String getA() {
        return a;
    }


    public void setA(String a) {
        this.a = a;
    }


    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Основная программа:

package com.test;

public class MainTestClone {
    public static void main(String[] args) throws CloneNotSupportedException {
        TestClone clone = new TestClone();
        clone.setA("RABA");

        TestClone clone2 = (TestClone) clone.clone();
        System.out.println(clone.getA());
        System.out.println(clone2.getA());
        System.out.println("---------------------------");
        clone.setA("DABA");
        System.out.println(clone.getA());
        System.out.println(clone2.getA());
        System.out.println("---------------------------");
        clone2.setA("Clone2 RABA DABA");
        System.out.println(clone.getA());
        System.out.println(clone2.getA());

    }
}

Вывод:

RABA
RABA
---------------------------
DABA
RABA <--- It does not change to DABA
---------------------------
DABA <--- No Changes here
Clone2 RABA DABA

Ответы [ 4 ]

2 голосов
/ 26 апреля 2020

Я думаю, что реальная проблема заключается в том, что вы вынули из контекста следующее определение и неправильно его истолковали:

"Мелкая копия - это та, в которой мы копируем только значения поля от одного объекта к другому. Это разные объекты, но проблема в том, что когда мы изменяем какие-либо свойства исходного адреса, это также влияет на адрес shallowCopy. "

Это явно ссылается на какой-то пример ... который вы не цитировали. (Отсюда мой комментарий о том, что вы вывели его из контекста!)

Чтобы это описание было правильным, свойства "исходного адреса" должны быть полями, отдельными объектами от того, который вы клонируете. Я представляю, что пример выглядит примерно так:

public class User implements Cloneable {
    String name;
    Address address; 
    ...
    public User clone() {
        return (User)(super.clone());
    }
}

public class Address {
    String street;
    String city;
    String zipCode;
}

, и они делают это:

Address address = new Address(...);
User user = new User("Fred", address);
User shallowCopy = user.clone();

, а затем

user.getAddress().setZipCode(...);

и наблюдают, что это меняется почтовый индекс, связанный с и оригиналом и клонированными User объектами.

Обратите внимание, что мы изменяем свойства Address, а не свойства User. Как ясно сказано в цитируемом тексте.


Но ваш пример другой. В этом вы (соответственно) изменяете поле исходных и клонированных объектов. И наблюдение, что назначение одного не влияет на другое.

То, что вы делаете, эквивалентно

shallowCopy.setAddress(new Address(...));

Если вы это сделали, то объект, на который ссылается shallowCopy, больше не будет быть поверхностной копией объекта, к которому относится user, и user.getAddress().setZipCode(...) больше не будет влиять на почтовый индекс shallowCopy или наоборот .

Короче говоря, причина что вы видите нечто отличное от того, что говорится в определении, это то, что вы делаете что-то другое.

Клон работает точно так, как указано. Проблема в том, что вы неверно истолковали или неправильно применили определение мелкой копии.

1 голос
/ 26 апреля 2020

Что бы вы ни реализовали, это только поверхностное копирование. Изменение атрибута исходного объекта не влияет на состояние объекта копирования, поскольку оно содержит только неизменяемые поля. Если бы он содержал какой-либо изменчивый объект, он бы затронул их обоих .

Если вы попытаетесь добавить другое поле любого типа класса и попытаетесь изменить значение поля этого класса, то изменения будут отражены как в объектах clone, так и в clone2.

1 голос
/ 26 апреля 2020

Мелкая копия о совместном использовании внутренних ссылок. Если вы измените ссылку напрямую, клон останется на старой ссылке, потому что это другой объект.

Вот почему имя мелкой копии или мелкое клонирование в Java. Если есть только поля примитивного типа или неизменяемые объекты, то нет разницы между мелкой и глубокой копией в Java. Вот почему здесь у вас на самом деле глубокая копия.

Если вы, например, замените String на Date, а затем измените содержимое даты (а не ссылку .. содержимое, подобное этому obj1.date().setTime(1) объект-клон будет отражать изменение, потому что оно указывает на одну и ту же ссылку Date.

Мы можем видеть копии, подобные этой

На мелкой копии clone2.date = clone.date

На глубокой копии clone2.date=new Date(clone.getTime());

0 голосов
/ 26 апреля 2020
super.clone

согласно Java Документы

Создает и возвращает копию этого объекта.

, следовательно, любые изменения, которые вы вносите в старый объект, будут независимыми недавно клонированного объекта. Таким образом, clone, clone2 - это отдельные Java объекты, сохраненные в другом пространстве памяти.

, если вы ищете повторяющиеся изменения к clone2, укажите оба ссылки на один и тот же объект. например,

TestClone clone2 = clone;
...