用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。即克隆最初的一个实例,包括它的属性。
让需要被拷贝的类继承Cloneable
重写里面clone()
class Sheep implements Cloneable {
String color;
int age;
//使用这个方法进行克隆
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Sheep() {
}
public Sheep(String color, int age) {
this.color = color;
this.age = age;
}
//这里忽略getset
}
浅拷贝
对于数据类型是基本数据类型的成员变量,浅拷贝会将该属性值复制一份给新的。
如果成员变量是引用数据类型,如:数组,对象的话,浅拷贝只会进行引用传递,即将成员变量的内存地址复制给新的实例。两个实例的成员变量指向相同的地址,如果进行修改,会影响到两个实例。默认使用clone()来实现
class Sheep implements Cloneable {
String color;
int age;
//使用引用数据类型
public Sheep friend ;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Sheep() {
}
public Sheep(String color, int age) {
this.color = color;
this.age = age;
}
}
进行浅拷贝的验证:
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sh = new Sheep("green", 2);
sh.friend = new Sheep("green",3);
Sheep clone = (Sheep) sh.clone();
System.out.printf(sh.friend.hashCode()+"====="+clone.friend.hashCode());
}
结果:
深拷贝
复制对象的所有基本数据类型的成员变量 为所有引用数据类型的成员变量申请存储空间,并复制其引用的对象。即不再指向相同的地址,而是复制。
深拷贝实现方式:
- 重写clone()
- 通过对象序列化
方法一:
修改Sheep里的clone()
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep newSheep = null;
//拷贝基本数据类型
newSheep = (Sheep) super.clone();
//拷贝引用类型
if (newSheep.friend != null) {
newSheep.friend = (Sheep) newSheep.friend.clone();
}
return newSheep;
}
运行main()结果:
方法二:
让Sheep继承Serializable
新创建一个方法
public Object sheepClone() {
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
Sheep newSheep = (Sheep) ois.readObject();
return newSheep;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {//关闭流
try {
oos.close();
ois.close();
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行main()结果: