目录
1、对象的克隆
1.1 对象的浅拷贝
1.2 对象深拷贝
1、对象的克隆
1.1 对象的浅拷贝
在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。
要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。
public class Person implements Cloneable { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } protected Object clone() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } } |
注意: 该Person 类实现了Cloneable 重写了clone() 方法.
public static void main(String[] args) { Person p1 = new Person("jack", 28); System.out.println(p1); Person p2 = (Person) p1.clone(); System.out.println(p2); // 不是同一个Person 对象. System.out.println(p1 == p2); // 修改p1 对象属性值,不影响 p2 对象的属性值. p1.setAge(30); System.out.println(p1); System.out.println(p2); } |
Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。
1.2 对象深拷贝
注意问题:
请看代码:
package cn.test.gz.myclone; public class Person implements Cloneable { private String name; private int age; private Address add; public Person() { } public Person(String name, int age, Address add) { this.name = name; this.age = age; this.add = add; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAdd() { return add; } public void setAdd(Address add) { this.add = add; } protected Object clone() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", add:" + add + "]"; } } package cn.test.gz.myclone; public class Address { private String country; private String city; public Address() { } public Address(String country, String city) { this.country = country; this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String toString() { return "country=" + country + ", city=" + city; } } |
注意:
Address add = new Address("中国", "广州"); Person p1 = new Person("jack", 28, add); add.setCountry("美国"); System.out.println(p1); Person p2 = (Person) p1.clone(); System.out.println(p2); // 克隆的是两个不同的对象 System.out.println(p1 == p2); // 但是对象内部的成员是同一个对象. System.out.println(p1.getAdd() == p2.getAdd()); |
解决办法:
package cn.test.gz.myclone; public class Address implements Cloneable { private String country; private String city; public Address() { } public Address(String country, String city) { this.country = country; this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String toString() { return "country=" + country + ", city=" + city; } @Override public Object clone() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return obj; } } |
Person 类
protected Object clone() { Person p = null; try { p = (Person) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } p.add = (Address) add.clone(); return p; } |
当然也可以通过序列化机制来实现对象的克隆.
public static void main(String[] args) throws IOException, ClassNotFoundException { Address add = new Address("中国", "广州"); Person p1 = new Person("jack", 28, add); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "c:\\person.txt")); oos.writeObject(p1); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c:\\person.txt")); Person p2=(Person)ois.readObject(); System.out.println(p1==p2); System.out.println(p1.getAdd()==p2.getAdd()); } |