1、克隆
克隆的含义就是:根据一个类复制另一个类,这个新的类内容与源类是相同的,但是内存地址不同。
在java中使用克隆的方式是:实现Cloneable 接口并实现clone()方法即可,一般是super.clone(),因为Cloneable是一个空接口
2、浅拷贝
克隆得到的类,只克隆了基本数据类型的数据,而没有克隆引用数据类型的数据,比如类中引用的对象等。具体如下面示例:
public class MSTest {
public static void main(String[] args) throws Exception{
UserInfo userInfo,userInfo2,userInfo3;
userInfo = new UserInfo();
userInfo2 = (UserInfo) userInfo.clone();
//克隆后两个对象内容相等但在内存中的位置不同
System.out.println(userInfo == userInfo2); //false
System.out.println(userInfo.equals(userInfo2));//true
//克隆后两对象中的引用类型是同一个,因此没有完全克隆
System.out.println(userInfo.getBody() == userInfo2.getBody()); //true
System.out.println(userInfo.getBody().equals(userInfo2.getBody())); //true
}
}
@Data
class UserInfo implements Cloneable{
private String name;
private String address;
private int age;
private Body body = new Body("111","222");
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserInfo userInfo = (UserInfo) o;
return age == userInfo.age &&
Objects.equal(name, userInfo.name) &&
Objects.equal(address, userInfo.address) &&
Objects.equal(body, userInfo.body);
}
}
@Data
class Body{
private String heigh;
private String weight;
Body(String heigh,String weight){
this.heigh = heigh;
this.weight = weight;
}
}
3、深拷贝
深拷贝会创建一个新的对象,并复制原对象的所有内容。对于引用数据类型,深拷贝会递归地复制其所有引用,直到基本类型,然后复制这些基本类型的值。
实现方式:
1、递归调用clone()
@Override
protected Object clone() throws CloneNotSupportedException {
UserInfo userInfo = (UserInfo) super.clone();
//获取了对象的基础类型,若对象中有引用类型,则它的clone()中也需要去获取这个引用的clone()
userInfo.body = (Body) userInfo.getBody().clone();
return userInfo;
}
@Data
class Body implements Cloneable{
private String heigh;
private String weight;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
Body(String heigh, String weight){
this.heigh = heigh;
this.weight = weight;
}
}
2、通过序列化获取
@Data
class UserInfo implements Cloneable,Serializable {
private String name;
private String address;
private int age;
private Body body = new Body("111","222");
protected Object clone() throws CloneNotSupportedException {
UserInfo userInfo = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
userInfo = (UserInfo) ois.readObject();
}catch (Exception e){
e.printStackTrace();
}
return userInfo;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserInfo userInfo = (UserInfo) o;
return age == userInfo.age &&
Objects.equal(name, userInfo.name) &&
Objects.equal(address, userInfo.address) &&
Objects.equal(body, userInfo.body);
}
}
4、深拷贝与浅拷贝区别
浅拷贝不拷贝引用类型,只是复制了对象的引用,而不进行创建对象。深拷贝会递归复制其所有引用,直到基本类型,然后复制这些基本类型的值。