Java:浅拷贝(克隆)不适合我?

Java:浅拷贝(克隆)不适合我?,java,clone,shallow-copy,Java,Clone,Shallow Copy,根据定义: 浅复制是只将字段值从一个对象复制到另一个对象的复制。它们是不同的对象,但问题是,当我们更改任何原始地址的属性时,这也会影响shallowCopy的地址 我试着看看对象1和对象2的值是否变得相同,所以我试着跟随,但无法这样做 public class TestClone implements Cloneable { private String a; public String getA() { return a; } public

根据定义:

浅复制是只将字段值从一个对象复制到另一个对象的复制。它们是不同的对象,但问题是,当我们更改任何原始地址的属性时,这也会影响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
根据Java文档

创建并返回此对象的副本

因此,对旧对象所做的任何更改都将独立于新克隆的对象。 所以克隆、克隆2是保存在不同内存空间中的独立Java对象

如果您正在查看复制对克隆2的更改,请将引用指向同一对象。 例如

根据Java文档

创建并返回此对象的副本

因此,对旧对象所做的任何更改都将独立于新克隆的对象。 所以克隆、克隆2是保存在不同内存空间中的独立Java对象

如果您正在查看复制对克隆2的更改,请将引用指向同一对象。 例如


浅拷贝是关于共享内部引用的。如果直接更改引用,克隆将保留在旧引用上,因为它是另一个对象

这就是为什么Java中称为浅拷贝或浅克隆的原因。如果只有原语类型字段或不可变对象,那么Java中的浅拷贝和深拷贝就没有区别。这就是为什么这里你有一个深度副本

例如,如果用日期替换字符串,然后修改日期内容而不是引用。类似于obj1.Date.setTime1的内容,克隆对象将反映更改,因为它指向相同的日期引用

我们可以看到这样的副本

在浅拷贝上clone2.date=clone.date


在深度复制clone2.date=new Dateclone.getTime

浅层复制是关于共享内部引用的。如果直接更改引用,克隆将保留在旧引用上,因为它是另一个对象

这就是为什么Java中称为浅拷贝或浅克隆的原因。如果只有原语类型字段或不可变对象,那么Java中的浅拷贝和深拷贝就没有区别。这就是为什么这里你有一个深度副本

例如,如果用日期替换字符串,然后修改日期内容而不是引用。类似于obj1.Date.setTime1的内容,克隆对象将反映更改,因为它指向相同的日期引用

我们可以看到这样的副本

在浅拷贝上clone2.date=clone.date


在深度复制clone2.date=new Dateclone.getTime

我认为真正的问题在于,你断章取义地曲解了以下定义:

浅复制是只将字段值从一个对象复制到另一个对象的复制。它们是不同的对象,但问题是,当我们更改任何原始地址的属性时,这也会影响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(...);
并注意到这会更改与原始用户对象和克隆用户对象关联的邮政编码

注意,我们正在更改地址的属性,而不是用户的属性。正如引用的文本明确指出的那样

但你的例子不同。分别更改原始对象和克隆对象的字段。并注意到分配一个不会影响另一个

你现在所做的相当于

shallowCopy.setAddress(new Address(...));
如果这样做,shallowCopy引用的对象将不再是用户引用的对象的浅层副本,并且user.getAddress.setZipCode。。。将不再影响shallowCopy的邮政编码,反之亦然

简言之,你看到与定义所说的不同的东西的原因是你在做不同的事情


克隆完全按照指定的方式工作。问题在于您误解了或误用了浅层复制的定义。

我认为真正的问题在于您断章取义地误解了以下定义:

浅复制是只将字段值从一个对象复制到另一个对象的复制。它们是不同的对象,但问题是,当我们更改任何原始地址的属性时,这也会影响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(...);
并注意到这会更改与原始用户对象和克隆用户对象关联的邮政编码

注意,我们正在更改地址的属性,而不是用户的属性。正如引用的文本明确指出的那样

但你的例子不同。分别更改原始对象和克隆对象的字段。并注意到分配一个不会影响另一个

你现在所做的相当于

shallowCopy.setAddress(new Address(...));
如果这样做,shallowCopy引用的对象将不再是用户引用的对象的浅层副本,并且user.getAddress.setZipCode。。。将不再影响shallowCopy的邮政编码,反之亦然

简言之,你看到与定义所说的不同的东西的原因是你在做不同的事情


克隆完全按照指定的方式工作。问题是您误解或误用了浅层复制的定义。

您所实现的只是浅层复制。更改原始对象的属性不会影响复制对象的状态,因为它只包含不可变字段。如果它包含任何可变对象,则会影响它们两个


如果尝试添加任何类类型的另一个字段,并尝试更改该类字段的值,则更改将反映在clone和clone2对象中

您所实现的只是浅层复制。更改原始对象的属性不会影响复制对象的状态,因为它只包含不可变字段。如果它包含任何可变对象,则会影响它们两个


如果尝试添加任何类类型的另一个字段,并尝试更改该类字段的值,则更改将反映在clone和clone2对象中

谢谢。我试图实现这样一种说法,即在浅层复制中,我们对对象所做的更改也将在克隆引用中看到;这将达到目的,因此,无论您对旧对象做什么更改,都将独立于新对象,而不是完全真实的。例如,如果字符串被日期替换,并且您修改了日期内容而没有更改引用,则克隆将看到相同的更改。@CodeScale是否确定两个克隆对象共享相同的内存?浅拷贝共享引用。。如果您修改引用的内容,两个都将看到更改。谢谢。我试图实现这样一种说法,即在浅层复制中,我们对对象所做的更改也将在克隆引用中看到;这将达到目的,因此,无论您对旧对象做什么更改,都将独立于新对象,而不是完全真实的。例如,如果字符串被日期替换,并且您修改了日期内容而没有更改引用,则克隆将看到相同的更改。@CodeScale是否确定两个克隆对象共享相同的内存?浅拷贝共享引用。。如果修改引用的内容,两者都将看到更改。