1. 概念
只是一个标记接口,本身并未抽象方法,被标记的对象会由Object使用本地方法来实现拷贝(浅拷贝)。
2. 使用
需要在要可以被拷贝的对象中
- 实现Cloneable接口(不实现就调用clone方法,会抛出CloneNotSupportedException克隆不被支持异常)
- 重写Object中的clone方法(不重写则使用Object中的clone方法,为浅拷贝)
在要拷贝处调用clone()方法
2.1. 使用Object中的clone方法实现浅拷贝实例
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
@AllArgsConstructor
public class Human implements Cloneable{
String name;
Dog dog;
@Override
public String toString(){
return "Human(name=" + name+",Dog="+dog+",hash="+this.hashCode()+")";
}
@SneakyThrows
public static void main(String[] args) {
Human lian = new Human("Lian",new Dog("Lucky"));
Human clone = (Human) lian.clone();
System.out.println(lian);
System.out.println(clone);
}
}
@AllArgsConstructor
class Dog {
String name;
@Override
public String toString(){
return "Dog(name=" + name+",hash="+this.hashCode()+")";
}
}
结果为:
Human(name=Lian,Dog=Dog(name=Lucky,hash=1134517053),hash=835648992)
Human(name=Lian,Dog=Dog(name=Lucky,hash=1134517053),hash=492228202)
此时Dog是同一个,Human则是不同的两个实例。
2.2. 使用自定义方法实现拷贝
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
@AllArgsConstructor
public class Human implements Cloneable {
String name;
Dog dog;
@Override
protected Object clone() throws CloneNotSupportedException {
Human clone = (Human) super.clone();
clone.dog=(Dog)dog.clone();
return clone;
}
@Override
public String toString() {
return "Human(name=" + name + ",Dog=" + dog + ",hash=" + this.hashCode() + ")";
}
@SneakyThrows
public static void main(String[] args) {
Human lian = new Human("Lian", new Dog("Lucky"));
Human clone = (Human) lian.clone();
System.out.println(lian);
System.out.println(clone);
}
}
@AllArgsConstructor
class Dog implements Cloneable{
String name;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Dog(name=" + name + ",hash=" + this.hashCode() + ")";
}
}
结果为:
Human(name=Lian,Dog=Dog(name=Lucky,hash=140435067),hash=1450495309)
Human(name=Lian,Dog=Dog(name=Lucky,hash=1670782018),hash=1706377736)
这时Human持有的Dog对象也是新的实例了。
3. Tip
浅拷贝和深拷贝的区别:拷贝对象的时候,对对象中对象字段这种引用数据类型的操作不同。深拷贝会继续解析引用的类型生成新的实例,再次进行深拷贝,一直递归下去。浅拷贝只会把引用类型的地址赋值到拷贝实例中,不会生成其他的实例对象。