一、使用场景
用克隆一个对象的方法去生成另一个对象。就比如一个类有很多属性,想创建多个对象,这些对象的大多数属性都相同,只有几个属性不同,可以先克隆,再设置不一样的值。
二、浅克隆
复制基本数据类型,引用类型没有进行复制,Object的clone()方法默认的克隆形式。被克隆的对象必须实现Cloneable接口,否则会报CloneNotSupportedException异常。Cloneable为标记接口,告诉jdk实现该接口的类可以被克隆,无具体内容。
package prototype;
public class ConcretePrototypeShallow implements Cloneable{
private int id;
private String next;
@Override
public ConcretePrototypeShallow clone() {
ConcretePrototypeShallow concretePrototype = null;
try {
concretePrototype = (ConcretePrototypeShallow)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return concretePrototype;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
}
package prototype;
public class Client {
public static void main(String[] args) {
ConcretePrototypeShallow concretePrototypeA = new ConcretePrototypeShallow();
concretePrototypeA.setId(1);
concretePrototypeA.setNext("abc");
ConcretePrototypeShallow concretePrototypeB = (ConcretePrototypeShallow)concretePrototypeA.clone();
System.out.println(concretePrototypeA.getNext() == concretePrototypeB.getNext());
}
}
打印为true,说明引用String类型next对象没有被复制,内存地址相同。
三、深克隆
复制基本数据类型和引用类型。
1.引用对象直接new值方法:
package prototype;
public class ConcretePrototypeDeep implements Cloneable{
private int id;
private String next;
@Override
public ConcretePrototypeDeep clone() {
ConcretePrototypeDeep concretePrototype = null;
try {
concretePrototype = (ConcretePrototypeDeep)super.clone();
concretePrototype.setNext(new String("abc"));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return concretePrototype;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
}
package prototype;
public class ClientDeep {
public static void main(String[] args) {
ConcretePrototypeDeep concretePrototypeA = new ConcretePrototypeDeep();
concretePrototypeA.setId(1);
concretePrototypeA.setNext("abc");
ConcretePrototypeDeep concretePrototypeB = (ConcretePrototypeDeep)concretePrototypeA.clone();
System.out.println(concretePrototypeA.getNext() == concretePrototypeB.getNext());
}
}
此时的打印为false。
2.用fastjson包:
package prototype;
import com.alibaba.fastjson.JSONObject;
public class ConcretePrototypeDeepFastjson implements Cloneable{
private int id;
private String next;
@Override
public ConcretePrototypeDeepFastjson clone() {
ConcretePrototypeDeepFastjson concretePrototype = null;
try {
concretePrototype = (ConcretePrototypeDeepFastjson)super.clone();
String nextClone = JSONObject.parseObject(JSONObject.toJSONBytes(concretePrototype.getNext()), String.class);
concretePrototype.setNext(nextClone);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return concretePrototype;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
}
package prototype;
public class ClientDeepfastjson {
public static void main(String[] args) {
ConcretePrototypeDeepFastjson concretePrototypeA = new ConcretePrototypeDeepFastjson();
concretePrototypeA.setId(1);
concretePrototypeA.setNext("abc");
ConcretePrototypeDeepFastjson concretePrototypeB = (ConcretePrototypeDeepFastjson)concretePrototypeA.clone();
System.out.println(concretePrototypeA.getNext() == concretePrototypeB.getNext());
}
}
3.使用ObjectStream
package prototype;
import java.io.*;
public class ConcretePrototypeDeepStream implements Cloneable, Serializable{
private int id;
private String next;
@Override
public ConcretePrototypeDeepStream clone() {
ConcretePrototypeDeepStream concretePrototypeDeepStream = null;
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return (ConcretePrototypeDeepStream)objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return concretePrototypeDeepStream;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
}