面试官:“说一下浅克隆和深克隆区别。”我:阿巴阿巴?

今天水群的时候看到群友分享的某厂面试关于深/浅克隆的一个问题,比较基础常见,整理出来跟各位大佬分享一波。

先说结论

  • 浅克隆:浅克隆会在堆上创建一个新的对象,
    • 如果属性是基本类型,克隆的就是基本类型的值;
    • 如果属性是引用类型,克隆会直接复制内部对象的引用地址,也就是说克隆对象和原对象共用同一个内部对象(对象地址相同)。
  • 深克隆 :深克隆会完全复制整个对象,包括这个对象所包含的内部对象。

在这里插入图片描述

浅克隆

浅克隆的示例很简单,我们这里实现了 Cloneable 接口,并重写了 clone() 方法。而 clone() 则是直接调用父类 Objectclone() 方法。

public class CloneDemo6 {
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        People p1 = new People(1, "张三", new Address("上海"));
        People p2 = p1.clone();

        System.out.println("a1 == a2:"+(p1.getAddress() == p2.getAddress()));
        System.out.println("p1:"+p1 + ",hashcode:" + p1.hashCode());
        System.out.println("p2:"+p2 + ",hashcode:" + p2.hashCode());
        System.out.println("a1:"+p1.getAddress() + ",hashcode:" + p1.getAddress().hashCode());
        System.out.println("a2:"+p2.getAddress() + ",hashcode:" + p2.getAddress().hashCode());

        p1.setId(2);
        p1.setName("李四");
        System.out.println("改变原对象p1的基本类型与引用类型后,输出结果:");
        p1.getAddress().setCity("北京");

        System.out.println("a1 == a2:"+(p1.getAddress() == p2.getAddress()));
        System.out.println("p1:"+p1 + ",hashcode:" + p1.hashCode());
        System.out.println("p2:"+p2 + ",hashcode:" + p2.hashCode());
        System.out.println("a1:"+p1.getAddress() + ",hashcode:" + p1.getAddress().hashCode());
        System.out.println("a2:"+p2.getAddress() + ",hashcode:" + p2.getAddress().hashCode());

    }

    @Data
    static class People implements Cloneable {
    
    
        private Integer id;
        private String name;
        private Address address;

        public People(Integer id, String name, Address address) {
    
    
            this.id = id;
            this.name = name;
            this.address = address;
        }

        @Override
        public People clone() throws CloneNotSupportedException {
    
    
            People people = (People) super.clone();
            return people;
        }
    }

    @Data
    static class Address implements Cloneable {
    
    
        private String city;

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

        @Override
        public Address clone() throws CloneNotSupportedException {
    
    
            return (Address) super.clone();
        }
    }

输出结果:
在这里插入图片描述
结论:

  • p1.getAddress()p2.getAddress() 两个对象相等;

  • 更改 p1 对象中基本类型变量的值,不会影响p2 中基本变量的值;
    总结:说明基础数据类型是值传递的,直接将属性值赋值给新的对象。修改其中一个对象的基础类型变量,不会影响另外一个对象中的基本类型变量。

  • 更改 p1 对象里的引用类型 address 对象 的值,p2 对象中的 address 对象的也会被更改;
    总结:说明 p1p2 共用了 address 对象;

  • 关于 String 类型值改变不影响另一个对象的原因;
    总结:String 是被 final 修饰的类 ,所以改变 String 修饰的变量,其实是创建了一个新的 String 对象,不会影响原对象;

深克隆

深克隆这里简单对 Person 类的 clone() 方法进行修改,克隆时把 Person 对象内部的 Address 对象一起克隆。

扫描二维码关注公众号,回复: 17282245 查看本文章
	@Override
    public People clone() throws CloneNotSupportedException {
    
    
        People people = (People) super.clone();
        // 修改此处(推荐使用序列化实现深克隆,此处所有引用类型都实现克隆会比较繁琐)
        people.setAddress(people.getAddress().clone());
        return people;
    }

输出结果:
在这里插入图片描述
从输出结构就可以看出,虽然 p1p2 包含的 Address 对象已经是不同的了。

结论:

  • p1.getAddress()p2.getAddress() 两个对象不相等;
  • 更改 p1 对象里的引用类型 address 对象 的值,p2 对象中的 address 对象的不会被更改;
    总结:说明深克隆克隆了原对象所有属性,并给克隆对象的内部属性指向的动态分配的内存;

感 谢 各 位 大 佬 的 阅 读,随 手 点 赞,日 薪 过 万~! !!

猜你喜欢

转载自blog.csdn.net/zhuzicc/article/details/122914250