转 https://blog.csdn.net/zhaoheng314/article/details/81985880
Java语言中克隆针对的是类的实例
/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/Cloneable.class
根据Cloneable接口的注释, 克隆需要遵循以下规则:
- 必须实现Cloneable接口
- 实现Cloneable的类应该重写clone(),重写时该方法的修饰符为public。
/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/Object.class
protected native Object clone() throws CloneNotSupportedException;
age属性是int类型,基本类型克隆时只是传值,不存在传引用
String类 final关键字 不可变特性,克隆对象修改了name属性的引用
深克隆
public class Student implements Cloneable{ private String name;//引用类型 final关键字 一是不可变,二是禁止指令重排 private int age;//基本类型 private Classes classes;//引用类型 public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } public void setClasses(Classes classes){ this.classes = classes; } public String getName(){ return name; } public Classes getClasses(){ return classes; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", classes=" + classes + "]"; } @Override protected Object clone() throws CloneNotSupportedException { Student stu = (Student)super.clone(); //克隆classes属性时候调用Classes类的clone(); Classes cla = (Classes)classes.clone(); stu.setClasses(cla); return stu; } }
public class Classes implements Cloneable{ private int classId;//基本类型 private String className;//引用类型 public void setClassId(int classId){ this.classId = classId; } public void setClassName(String className){ this.className = className; } @Override public String toString() { return "Classes [classId=" + classId + ", className=" + className + "]"; } @Override protected Object clone() throws CloneNotSupportedException{ return super.clone(); } }
public class TestClone { public static void main(String[] args) { Student stu = new Student(); stu.setName("张三"); stu.setAge(10); Classes classes = new Classes(); classes.setClassId(101); classes.setClassName("一班"); stu.setClasses(classes); try{ System.out.println("深克隆测试-----"); //克隆 Student stu2 = (Student)stu.clone(); System.out.println("两个对象是否相同:" + (stu == stu2)); System.out.println("两个对象name属性是否相同:" + (stu.getName() == stu2.getName())); System.out.println("两个对象classes是否相同:" + (stu.getClasses() == stu2.getClasses())); System.out.println("深克隆,Stu" + stu); System.out.println("深克隆,Stu2" + stu2); System.out.println("修改克隆对象属性"); stu2.setName("李四"); // public final class String 一是不可变,二是禁止指令重排 修改了name属性的引用 stu2.setAge(20); stu2.getClasses().setClassId(102); stu2.getClasses().setClassName("二班"); System.out.println("修改克隆对象属性后,Stu " + stu); System.out.println("修改克隆对象属性后,Stu2 " + stu2); }catch (CloneNotSupportedException e){ e.printStackTrace(); } } }