Java中的深拷贝和浅拷贝_Java中的深拷贝和浅拷贝

摘自《Java Core》 ed.11

In this section, we discuss the Cloneable interface that indicates that a class has provided a safe clone method. Since cloning is not all that common, and the details are quite technical, you may just want to glance at this material until you need it.

To understand what cloning means, recall what happens when you make a copy of a variable holding an object reference. The original and the copy are references to the same object (see Figure 6.1). This means a change to either variable also affects the other.

f97aec56c08455e4fc7d0b10f263c4aa.png

持有一个对象引用的变量的复制(copy)和之前的变量引用的是同一个对象,这代表着一个变量上的操作会影响到另一个变量

var original = new Employee("John Public", 50000);

Employee copy = original;

copy.raiseSalary(10); // oops--also changed original

If you would like copy to be a new object that begins its life being identical to original but whose state can diverge over time, use the clone method.

如果需要从一个原始对象中复制一个对象,且之后可以自由改变状态,那么需要使用clone()方法

Employee copy = original.clone();

copy.raiseSalary(10); // OK--original unchanged

But it isn’t quite so simple. The clone method is a protected method of Object, which means that your code cannot simply call it. Only the Employee class can clone Employee objects. There is a reason for this restriction. Think about the way in which the Object class can implement clone. It knows nothing about the object at all, so it can make only a field-by-field copy. If all data fields in the object are numbers or other basic types, copying the fields is just fine. But if the object contains references to subobjects, then copying the field gives you another reference to the same subobject, so the original and the cloned objects still share some information.

clone()是Object的一个protected方法,只有Employee类可以克隆Employee对象(需要实现Cloneable接口,在其它类中无法调用)。如果一个类中所有的成员变量都是基本数据类型,那么直接克隆没有问题,然而它的成员变量如果有其它的子对象,那么原始对象和克隆对象还是有一些共享信息

To visualize that, consider the Employee class that was introduced in Chapter4. Figure 6.2 shows what happens when you use the clone method of the Object class to clone such an Employee object. As you can see, the default cloning operation is “shallow”—it doesn’t clone objects that are referenced inside other objects. (The figure shows a shared Date object. For reasons that will become clear shortly, this example uses a version of the Employee class in which the hire day is represented as a Date.)

c01982b3f43b7ce1a5411216cae55fd5.png

默认的克隆操作时,不会克隆在对象中引用的其他对象。图中可以看到String和Date的字段都没有被克隆

Does it matter if the copy is shallow? It depends. If the subobject shared between the original and the shallow clone is immutable, then the sharing is safe. This certainly happens if the subobject belongs to an immutable class, such as String. Alternatively, the subobject may simply remain constant throughout the lifetime of the object, with no mutators touching it and no methods yielding a reference to it.

Quite frequently, however, subobjects are mutable, and you must redefine the clone method to make a deep copy that clones the subobjects as well. In our example, the hireDay field is a Date, which is mutable, so it too must be cloned. (For that reason, this example uses a field of type Date, not LocalDate, to demonstrate the cloning process. Had hireDay been an instance of the immutable LocalDate class, no further action would have been required.)

浅拷贝,在类的成员变量都是"immutable"(该类型对象本身无法被改变)或者在其生命周期中不变时,或者没有改变器(改变方法)访问它或者别的方法产生对它的引用时,直接调用clone()方法没有问题,一旦有mutable的子对象(例如List),那么必须要重新定义clone方法来保证深拷贝(同样复制子对象)

注:LocalDate是immutable的

For every class, you need to decide whether

The default clone method is good enough;

The default clone method can be patched up(调用) by calling clone on the mutable subobjects; or

clone should not be attempted.

The third option is actually the default. To choose either the first or the second option, a class must

Implement the Cloneable interface; and

Redefine the clone method with the public access modifier.

实现深拷贝

实现Cloneable接口

使用public访问控制符来覆写clone方法

Cloneable接口是一个标记接口,本身不提供方法,clone()是从Object中继承下来的方法

final修饰的class可以在clone方法内将CloneNotSupportedException捕获并处理,否则只需要在方法后加上throws标价即可,这样的话可以让子类在不允许clone时抛出此异常

注意:当子类实现clone方法,那么父类会调用子类的clone方法,如果父类还有其他的成员变量是mutable的,那么父类的clone还是会有问题

clone的应用并没有那么多,记住目前这些就够了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值