V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gzk329
V2EX  ›  Java

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

  •  
  •   gzk329 · 238 天前 · 643 次点击
    这是一个创建于 238 天前的主题,其中的信息可能已经有所发展或是发生改变。

    测试类

    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;
        }
    }
    
    5 条回复    2021-04-09 15:45:02 +08:00
    misaka19000
        1
    misaka19000  
       238 天前
    Person 的 equals 是不是被重写了
    cnxobo
        2
    cnxobo  
       238 天前
    浅拷贝的简单理解为创建一个新实例然后属性用 = 一个一个的赋值过去。
    p1 p2 指向的是不同的对象,但是 p1 p2 的引用类型属性指向的对象是一样的。
    也就是 p1.addr 就是 p2.addr 。
    如果你不 p2.setAddr, 直接 p2.getAddr().setCity("苏州市"), 那么 p1 和 p2 的 addr city 都会变成苏州市。
    beichenhpy
        3
    beichenhpy  
       238 天前
    直接打印内存地址看看不就完了
    gzk329
        4
    gzk329  
    OP
       238 天前
    @cnxobo 明白了 谢谢
    beichenhpy
        5
    beichenhpy  
       238 天前
    应该要重写 equals()和 hashCode()吧。。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2197 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 05:15 · PVG 13:15 · LAX 21:15 · JFK 00:15
    ♥ Do have faith in what you're doing.