目录
赋值操作
@Getter
@Setter
public class User {
private String name;
private Address address;
}
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Address {
private String city;
}
新对象通过复制原始对象得到
public class TestClone {
public static void main(String[] args) {
Address address = new Address();
address.setCity("BJ");
User user1 = new User();
user1.setName("zhangsan");
user1.setAddress(address);
User user2 = user1; //赋值
System.out.println("user1: " + user1.getName() + "," + user1.getAddress().getCity());
System.out.println("user2: " + user2.getName() + "," + user2.getAddress().getCity());
System.out.println("user是否相等:" + (user1 == user2)); //是同一个地址
System.out.println("=====修改原始对象=====");
user1.setName("lisi");
user1.getAddress().setCity("SH");
System.out.println("user1: " + user1.getName() + "," + user1.getAddress().getCity());
System.out.println("user2: " + user2.getName() + "," + user2.getAddress().getCity());
}
}
输出结果:
user1和user2就是同一个对象
新对象user2中的基本类型和引用类型的属性都会随user1中的变化而变化
user1: zhangsan,BJ
user2: zhangsan,BJ
user是否相等:true
=====修改原始对象=====
user1: lisi,SH
user2: lisi,SH
浅克隆
基本类型的属性复制值, 引用类型的属性复制地址
克隆: 实现 Cloneable 接口, 重写Object类中的 clone() 方法
类User实现clone()方法
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User implements Cloneable {
private String name;
private Address address;
@Override
public User clone() {
User clone = null;
try {
clone = (User)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
新对象通过克隆原始对象得到
public class TestClone {
public static void main(String[] args) {
Address address = new Address();
address.setCity("BJ");
User user1 = new User();
user1.setName("zhangsan");
user1.setAddress(address);
User user2 = user1.clone(); //克隆对象
System.out.println("user1: " + user1.getName() + "," + user1.getAddress().getCity());
System.out.println("user2: " + user2.getName() + "," + user2.getAddress().getCity());
System.out.println("user是否相等:" + (user1 == user2));
System.out.println("=====修改原始对象=====");
user1.setName("lisi");
user1.getAddress().setCity("SH");
System.out.println("user1: " + user1.getName() + "," + user1.getAddress().getCity());
System.out.println("user2: " + user2.getName() + "," + user2.getAddress().getCity());
}
测试结果:
对象地址不一样, user1和user2已经不是同一个对象了
新对象中的基本类型的属性name不受user1的影响
引用类型属性会随着user1中的变化而变化, 因为二者的引用类型属性指向的还是同一个地址
user1: zhangsan,BJ
user2: zhangsan,BJ
user是否相等:false
=====修改原始对象=====
user1: lisi,SH
user2: zhangsan,SH
深克隆
基本类型属性和引用类型属性都和原始对象中的完全独立
引用类型属性的类Address也实现 clone() 方法
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Address implements Cloneable {
private String city;
@Override
public Address clone() {
Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}
}
User中的clone()方法中调用引用类型属性的克隆
@Getter
@Setter
public class User implements Cloneable {
private String name;
private Address address;
@Override
public User clone() {
User clone = null;
try {
clone = (User)super.clone();
//引用类型属性的克隆
Address newAddress = address.clone();
clone.setAddress(newAddress);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
测试结果:
新旧对象的地址不一样
user2的基本类型属性name 和 引用类型属性address 都不受原始对象的影响
user1: zhangsan,BJ
user2: zhangsan,BJ
user是否相等:false
=====修改原始对象=====
user1: lisi,SH
user2: zhangsan,BJ
常见的深克隆方式
1. 所有引用属性都实现克隆,整个对象就变成了深克隆。
上面的深克隆示例就是这种
2. 使用 JDK 自带的字节流序列化和反序列化对象实现深克隆。
//类必须实现Serializable接口
public class Address implements Serializable {/*...*/}
public class User implements Serializable {/*...*/}
//深克隆 java.io.*
User user2 = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(user1);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
user2 = (User) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
3. 使用第三方工具实现深克隆
比如 Apache Commons Lang。
4. 使用 JSON 工具
如 GSON、FastJSON、Jackson 序列化和反序列化对象实现深克隆。
//fastjson
String str = JSONObject.toJSONString(user1);
User user2 = JSONObject.parseObject(str, User.class);
参考
浅克隆和深克隆有什么区别?
https://www.cnblogs.com/javacn123/p/17407411.html
什么是深克隆,浅克隆?(案例详解)
https://www.cnblogs.com/blessing2022/p/16622041.html
浅克隆和深克隆
https://blog.csdn.net/ChineseSoftware/article/details/122942803