Posts Java 对象克隆
Post
Cancel

Java 对象克隆

什么是对象克隆

如果为一个包含对象引用的变量建立副本,原变量和副本都是同一个对象的引用。任何一个变量的改变都会影响另一个变量。

复制

1
2
3
Employee original = new Employee("Tom", 50000);
Employee copy = original;
copy.riseSalary(10);	// 会影响 original

如果希望 copy 是一个新对象,它的初始状态与 original 相同,但是之后他们各自有自己的状态,这种情况下就可以使用 clone 方法。

克隆

1
2
Employee copy = original.clone();
copy.riseSalary(10);	// 不改变 original

浅克隆与深克隆

如果对象只包含基本类型,那么浅克隆没有问题;如果对象包含子对象的引用,克隆域就会得到相同子对象的另一个引用,这样一来,原对象和克隆对象仍然会共享一些信息。

浅克隆

如果原对象和浅克隆对象共享的子对象是不可变的,那么这种克隆是安全的。但是通常子对象都是可变的,必须重新定义 clone 方法来建立一个深克隆,同时克隆所有子对象。

对于每一个类,需要确定:

  1. 默认的 clone 方法是否满足需求;
  2. 是否可以在可变的子对象上调用 clone 来修补默认的 clone 方法;
  3. 是否不该使用 clone。

对于第 1 项或 第 2 项,类必须:

  1. 实现 Cloneable 接口;
  2. 重新定义 clone 方法,并指定 public 访问修饰符。

Object 类中的 clone 方法声明为 protected,所以不能直接调用 anObject.clone() 。子类只能调用受保护的 clone 方法来克隆它自己的对象。必须重新定义 clone 为 public 才能允许所有方法克隆对象。

这里 Cloneable 接口只是作为一个标记,如果一个对象请求克隆,但没有实现这个接口,就会抛出一个受检查异常。

即使 clone 默认的浅拷贝能够满足要求,还是需要实现 Cloneable 接口,将 clone 定义为 public,再调用 super.clone() 。

1
2
3
4
5
6
class Employee implements Cloneable {
    public Employee clone() throws CloneNotSupportedException {
        return (Employee) super.clone();
    }
    ...
}

建立深克隆:

1
2
3
4
5
6
7
8
9
10
11
12
class Employee implements Cloneable {
    ...
    public Employee clone() throws CloneNotSupportedException {
        // 克隆自己
        Employee cloned = (Employee) super.clone();
        // 克隆可变的域
        cloned.hireDay = (Date) hireDay.clone();
        
        return cloned;
    }
    ...
}

实际上,克隆并不常用,标准库只有不到 5% 的类实现了 clone 。

OLDER POST NEWER POST

Comments powered by Disqus.

内容

Search Results