Object 类中的 clone 方法应该是 shallow 拷贝 那应该是 p1 p2 指向同一个对象 为什么我实际使用的时候却不对?

2021-04-09 15:12:21 +08:00
 gzk329

测试类

public class TestCopy {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person("张三", 18, new Address("江苏省", "无锡市"));
        System.out.println(p1);
        //Person{pname='张三', page=18, addr=Address{province='江苏省', city='无锡市'}}

        Person p2 = (Person) p1.clone();
        System.out.println(p1 + " \n" + p2);
        //Person{pname='张三', page=18, addr=Address{province='江苏省', city='无锡市'}}
        //Person{pname='张三', page=18, addr=Address{province='江苏省', city='无锡市'}}

        System.out.println(p1.equals(p2));
        //false

        Address addr2 = new Address("江苏省", "苏州市");
        p2.setAddr(addr2);
        System.out.println("修改地址后===========================================");
        
        System.out.println(p1);
        System.out.println(p2);
        //Person{pname='张三', page=18, addr=Address{province='江苏省', city='无锡市'}}
        //Person{pname='张三', page=18, addr=Address{province='江苏省', city='苏州市'}}
    }
}
源码注释也写的很清楚
Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
public class Person implements Cloneable{
    private String pname;
    private int page;
    private Address addr;

    public Person() {
    }

    public Person(String pname, int page, Address addr) {
        this.pname = pname;
        this.page = page;
        this.addr = addr;
    }

    @Override
    public String toString() {
        return "Person{" +
                "pname='" + pname + '\'' +
                ", page=" + page +
                ", addr=" + addr +
                '}';
    }

    public void showAll(){
        System.out.println("名字是:" + this.pname + ",年龄是:" + page + ",地址(省+市)是:" + addr.getProvince() + addr.getCity());
    }


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


    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public Address getAddr() {
        return addr;
    }

    public void setAddr(Address addr) {
        this.addr = addr;
    }
}

public  class Address{
    private String province;
    private String city;

    public Address() {
    }

    public Address(String province, String city) {
        this.province = province;
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}
1260 次点击
所在节点    Java
5 条回复
misaka19000
2021-04-09 15:14:55 +08:00
Person 的 equals 是不是被重写了
cnxobo
2021-04-09 15:28:54 +08:00
浅拷贝的简单理解为创建一个新实例然后属性用 = 一个一个的赋值过去。
p1 p2 指向的是不同的对象,但是 p1 p2 的引用类型属性指向的对象是一样的。
也就是 p1.addr 就是 p2.addr 。
如果你不 p2.setAddr, 直接 p2.getAddr().setCity("苏州市"), 那么 p1 和 p2 的 addr city 都会变成苏州市。
uselessVisitor
2021-04-09 15:33:21 +08:00
直接打印内存地址看看不就完了
gzk329
2021-04-09 15:38:20 +08:00
@cnxobo 明白了 谢谢
uselessVisitor
2021-04-09 15:45:02 +08:00
应该要重写 equals()和 hashCode()吧。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/769450

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX