1、浅拷贝(无法拷贝引用类型属性)
(1)代码
import lombok.AllArgsConstructor;
import lombok.Data;
public class Test {
public static void main(String[] args) {
// 准备数据
Address address = new Address("武汉", "汉正街");
Person person = new Person("明快de玄米61", 60, address);
// 进行拷贝
Person clone = person.clone();
// 设置拷贝数据中的对象属性里的字符串值
clone.getAddress().setCity("北京");
// 打印原数据中的对象属性里的字符串值
System.out.println("原来城市:" + person.getAddress().getCity());
}
}
@Data
@AllArgsConstructor
class Person implements Cloneable {
private String userName;
private int age;
private Address address;
@Override
protected Person clone() {
try {
// 浅拷贝(调用父类的 clone() 方法,实现浅拷贝)
Person clone = (Person) super.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
@Data
@AllArgsConstructor
class Address {
private String city;
private String streetName;
}
(2)结果
原来城市:北京
2、深拷贝(手动拷贝引用类型属性)
(1)代码
import lombok.AllArgsConstructor;
import lombok.Data;
public class Test {
public static void main(String[] args) {
// 准备数据
Address address = new Address("武汉", "汉正街");
Person person = new Person("明快de玄米61", 60, address);
// 进行拷贝
Person clone = person.clone();
// 设置拷贝数据中的对象属性里的字符串值
clone.getAddress().setCity("北京");
// 打印原数据中的对象属性里的字符串值
System.out.println("原来城市:" + person.getAddress().getCity());
// 打印拷贝数据中的对象属性里的字符串值
System.out.println("修改城市:" + clone.getAddress().getCity());
}
}
@Data
@AllArgsConstructor
class Person implements Cloneable {
private String userName;
private int age;
private Address address;
@Override
protected Person clone() {
try {
// 浅拷贝(先调用父类的 clone() 方法,实现浅拷贝)
Person clone = (Person) super.clone();
// 深拷贝(手动处理引用类型字段,实现深拷贝)
clone.address = address.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
@Data
@AllArgsConstructor
class Address implements Cloneable {
private String city;
private String streetName;
@Override
public Address clone() {
try {
Address clone = (Address) super.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
(2)结果
原来城市:武汉
修改城市:北京
(3)代码说明
1、Address 类:
- 实现了 Cloneable 接口。
- 重写了 clone() 方法,调用父类的 clone() 方法来实现浅拷贝。
- 由于 Address类中的字段都是值类型(String),浅拷贝已经足够。
2、Person 类:
- 实现了 Cloneable 接口。
- 重写了 clone() 方法:
- 先调用父类的 clone() 方法,实现浅拷贝。
- 手动处理引用类型字段 address,调用 address.clone() 方法来实现深拷贝。
3、测试代码:
- 创建了一个原始的 Person 对象和它的 Address。
- 使用 clone() 方法创建了一个深拷贝的 Person 对象。
- 修改了深拷贝对象的字段,验证深拷贝的对象是否独立于原始对象。
(4)注意事项
- clone() 方法默认是浅拷贝,如果需要深拷贝,必须手动处理引用类型字段。
- Cloneable 接口只是一个标记接口,没有方法定义。实际的克隆操作需要在 clone() 方法中实现。
- 使用 clone() 方法时,必须处理 CloneNotSupportedException 异常。
- 如果类中包含复杂的引用类型字段,深拷贝的实现可能会变得较为复杂,需要递归地处理每一个引用类型字段。