Java中的复本能分成深复本(Deep Copy)、浅复本(Shallow Copy)和提及复本(Reference Copy)。它间的差别如下表所示:
浅复本:
只拷贝第一类这类,而不拷贝第一类包涵的子第一类。旧有第一类间共享资源子第一类的提及,即新第一类和原初第一类中的子第一类对准同一物理地址。
浅复本:采用clone()形式或是Object类的copy()形式。
深复本:
不但拷贝第一类这类,更要拷贝第一类包涵的大部份子对象。新第一类和原初第一类所包涵的子第一类是互相分立的。
深复本:能透过格式化和反格式化、递回结点等形式来同时实现。
提及复本:
只拷贝第一类的提及,而不拷贝第一类这类。旧有第一类间共享资源同一第一类示例,即它的提及对准同两个物理地址。
提及复本:间接将第一类的提及表达式给另两个表达式方可。
比如,下列标识符模拟了提及复本和浅复本的差别:
class Person { public String name; public intage; }public class CopyDemo { public static void main(String[] args) { Person p1 = newPerson(); p1.name =“Alice”; p1.age = 20; Person p2 = p1; // 提及复本 System.out.println(p1 == p2); // true, 提及成正比System.out.println(p1.name == p2.name); // true, 字符串常量池中的提及相同 System.out.println(p1.age == p2.age); // true, 基本数据类型的值相同 Person p3 = (Person)p1.clone(); // 浅复本 System.out.println(p1 == p3); // false, 提及不成正比 System.out.println(p1.name == p3.name); // true, 字符串常量池中的提及相同 System.out.println(p1.age == p3.age); // true, 基本数据类型的值相同 } }在上面的标识符中,p1和p2是两个第一类的提及,它对准同一第一类示例。在采用提及复本时,p2和p1共享资源同一第一类示例,所以它的属性值成正比,并且两个提及也是成正比的。
而当采用浅复本时,p3是透过调用p1的clone()形式来拷贝p1的第一类的。由于这种形式只是拷贝了第一类这类,而没有拷贝第一类包涵的子第一类,所以p1和p3提及不同的第一类示例。但由于name属性的值是字符串常量,字符串常量池中只有两个示例,所以p1和p3的name属性对准同一第一类。但age是两个基本数据类型,不是两个第一类,所以p1和p3的age属性值成正比。
比如,下列标识符模拟了深复本和浅复本的差别:
public class Address implements Cloneable { private String name; @Override public Address clone() { try { return (Address) super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(); } } } public class Person implements Cloneable { public String name; public int age; private Address address; // 省略构造函数、Getter&Setter形式 @Override public Person clone() { try { Person person = (Person) super.clone(); returnperson; }catch (CloneNotSupportedException e) { throw new AssertionError(); } } }测试 :
Person person1=new Person(new Address(“武汉”)); Person person1Copy=person1.clone(); // true System.out.println(person1.getAddress()==person1Copy.getAddress());从输出结构就能看出, person1 的克隆第一类和 person1 采用的仍然是同一 Address第一类。
深复本
这里我们简单对 Person 类的 clone() 形式进行修改,连带着要把 Person 第一类内部的 Address 第一类一起拷贝。
@Override public Person clone(){ try{ Person person=(Person)super.clone(); person.setAddress(person.getAddress().clone()); returnperson; }catch(CloneNotSupportedException e){ throw new AssertionError(); } }测试 :
Person person1 =new Person(new Address(“武汉”)); Person person1Copy = person1.clone(); // false System.out.println(person1.getAddress() == person1Copy.getAddress());从输出结构就能看出,虽然 person1 的克隆第一类和 person1 包涵的 Address第一类已经是不同的了。