什么是克隆
??克隆顾名思义,就是可以将一个对象的信息克隆一份出来,生成一个新的对象。那么肯定就有人问了,都有new了,为什么还要克隆? 因为new出来的对象,属性都是初始化的值,而clone出来的对象,能保存对象的现有状态,当我们需要临时保存一个对象的现有状态时,就可以使用clone,如果用new,还需要重新赋值,当属性较多时,会比较繁琐。并且clone是native方法,是与底层操作系统交互的,会更加的快捷。 注意:
- Person p = new Person; Person p1 = p; 这样不是对象克隆,只是想Person对象的引用复制给了p2,两个引用指向同一个对象,实际上操作的还是同一个。而克隆出来的是一个新的对象。
- 被克隆的类一定要实现Cloneable接口,该接口没有任何方法,相当于一种能力,表示实现该接口的类可以被clone。然后再重写Object类中的clone()方法

克隆的分类
??克隆分为两类,浅克隆,深克隆。
浅克隆
??浅克隆(Shallow Clone),如果对象的属性是基本数据类型或String类型,则复制一份给克隆对象;如果是引用类型,那么就将引用对象的地址复制给克隆对象。
public class Person implements Cloneable{
private int age;
private String name;
private Address address;
@Override
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", address=" + address +
'}';
}
}
public class ShallowCloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
person1.setAge(22);
person1.setName("张三");
Address address = new Address("北京");
person1.setAddress(address);
Person person2 = person1.clone();
person2.getAddress().setName("南京");
System.out.println(person1);
System.out.println(person2);
System.out.println(person1 == person2);
}
}
结果如下:  可以看到,当对象的属性为基本类型时,会直接复制一份给新对象,如果是引用类型,则将引用类型的地址复制给新对象,改变一个引用类型引所引用对象的值,相当于两个对象一起改变。
深克隆
??深克隆(Deep Clone),如果是基本数据类型,则直接复制一份给克隆对象,如果是引用类型,则将所引用的对象也克隆复制一份给克隆对象。
package clone.bean;
public class Person implements Cloneable{
private int age;
private String name;
private Address address;
@Override
public Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.address = (Address) address.clone();
return person;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", address=" + address +
'}';
}
}
public class DeepCloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
person1.setAge(22);
person1.setName("张三");
Address address = new Address("北京");
person1.setAddress(address);
Person person2 = person1.clone();
person2.getAddress().setName("南京");
System.out.println(person1);
System.out.println(person2);
System.out.println(person1 == person2);
}
}
结果如下:  深克隆成功,但是如果当对象引用类型过多,则重写方法则变得麻烦起来,那么就可以使用序列化来实现深克隆,将对象保存在流中。
public class DeepCloneTest2 {
public static void main(String[] args) throws Exception {
Person p1 = new Person();
p1.setAge(22);
p1.setName("张三");
Address address = new Address("浙江");
p1.setAddress(address);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(p1);
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Person o = (Person) ois.readObject();
System.out.println(o);
Person p2 = p1.clone();
p2.getAddress().setName("陕西");
System.out.println(p2);
ois.close();
bos.close();
}
}
|