java核心技术卷案例_克隆

克隆的正常使用

.clone() 方法是 Object 类的一个 protected 方法

protected native Object clone() throws CloneNotSupportedException;

也就是说子类无法直接继承 Object 的 clone() 方法,只能在子类中通过 super 关键字来调用
而且 clone() 返回的数据类型是 Object ,但我们通常想直接克隆出一个同类型的新对象.
因此,我们需要自己在子类中自己声明一个 clone() 方法,在方法中用 super 关键字调用Object.clone()
然后在强转成想用类型的对象返回,完成一次克隆

	// Person 类
    static class Person {
        private Pocket pocket; // 包含一个引用对象
		
		/** 声明一个克隆方法 */
        public Person clone() throws CloneNotSupportedException {
            return (Person) super.clone();
        }
    }
    // Pocket 类
	static class Pocket {
        private int mony;
    }

尝试克隆

	public static void main(String[] args) {
        Person person1 = new Person();
        Pocket pocket = new Pocket();
        pocket.mony = 100;
        person1.pocket = pocket;
        Person person2 = null;
        try {
            person2 = person1.clone(); // 克隆
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

执行结果:
在这里插入图片描述
原因是少了一个步骤,要使用 super.clone() ,必须要实现一个标记接口 Cloneable,表示这个类是可以克隆的,所以我们修改一下

	// Person 类
    static class Person implements Cloneable {
        private Pocket pocket; // 包含一个引用对象
		
		/** 声明一个克隆方法 */
        public Person clone() throws CloneNotSupportedException {
            return (Person) super.clone();
        }
    }
    // Pocket 类
	static class Pocket {
        private int mony;
    }

再次执行就没问题啦

克隆是浅拷贝

上面的案例中 Person 对象中包含一个 Pocket 类型的引用
我们试试用 person1 克隆出 person2 后修改 person1 引用对象的 mony 属性,看看 person2 的 mony 有没有变化

public static void main(String[] args) {
        Person person1 = new Person();
        Pocket pocket = new Pocket();
        pocket.mony = 100;
        person1.pocket = pocket;
        Person person2 = null;
        try {
            person2 = person1.clone(); // 克隆
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println("修改前person1.pocket.mony = " + person1.pocket.mony);
        if (!ObjectUtils.isEmpty(person2)) {
            System.out.println("修改前person2.pocket.mony = " + person2.pocket.mony);
        }
        person1.pocket.mony = 200; // 修改 person1 的 pocket 对象的 属性值
        System.out.println("修改后person1.pocket.mony = " + person1.pocket.mony);
        if (!ObjectUtils.isEmpty(person2)) {
            System.out.println("修改后person2.pocket.mony = " + person2.pocket.mony);
        }
    }

结果
在这里插入图片描述
就是说克隆对于引用变量是拷贝了一份引用,而没有把引用指向的对象也给克隆一个新的对象再引用它
那么实现深克隆就要手动去把 Person 类的所有引用对象给克隆一份,可以之间new对象赋值,也可以让Pocket 对象也实现 Cloneable 接口用.clone() 方法克隆

	static class Person implements Cloneable {
        private Pocket pocket;

        public Person clone() throws CloneNotSupportedException {
            Person clone = (Person) super.clone();
            Pocket newPocket = new Pocket();
            newPocket.mony = clone.pocket.mony;
            clone.pocket = newPocket; // 引用新对象
            return clone;
        }
    }

结果
在这里插入图片描述
这样表示克隆出来的就是一个船新的对象啦

小疑问

如果一个对象的引用链非常长非常深,那要深拷贝一个对象不是麻烦死?
要一层一层 new 对象赋值?
看来克隆只适合引用层比较浅的对象啊
我直接用 BeanUtils.copy() 不香吗?
啥?BeanUtils.copy()也是浅拷贝?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值