1.功能
由方法名(克隆)可知是复制一个对象,方法调用后会创建并返回此对象的一个副本。
2.为什么不用 “=” 以赋值的方式创建对象副本?
Student stu1 = new Student("zhaoliu",18,"1996-11-20");
Student stu2 = stu1;
stu2.setName("lisi");
System.out.println(stu1);
System.out.println(stu2);
//执行结果:
Student [name=lisi, age=18, birthday=1996-11-20]
Student [name=lisi, age=18, birthday=1996-11-20]
这里只对stu2的name属性重新赋值,然而stu1的name属性值也改变了.
再看下面的代码
Student stu1 = new Student("deng",18,"1996-11-20");
Student stu2 = stu1;
System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());
把对象stu1赋值给stu2, 其实只是将对象的引用赋值给了stu2, 将两个对象的hashcode打印.
可以看出,stu1和stu2其实是同一个对象.
可见要复制一个对象,用”=”是不可行的.
2.clone的使用方法
实现Cloneable接口,重写clone方法.
Student stu1 = new Student("zhaoliu",18,"1996-11-20");
Student stu2 = (Student) stu1.clone();
stu2.setName("lisi");
System.out.println(stu1);
System.out.println(stu2);
System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());
执行结果如下
从代码执行结果可以看出, 现在的stu2和stu1是两个不同的对象.
3.深拷贝和浅拷贝
clone方法虽实现了对象的复制,这里存在一个深拷贝和浅拷贝的问题.
Student stu1 = new Student("zhaoliu",18,"1996-11-20");
Student stu2 = (Student) stu1.clone();
System.out.println(stu1.getName().hashCode());
System.out.println(stu2.getName().hashCode());
执行结果:
-323273412
-323273412
可见两个对象的name属性是同一个String对象.
当改变stu1的 name属性值后
Student stu1 = new Student("zhaoliu",18,"1996-11-20");
Student stu2 = (Student) stu1.clone();
stu2.setName("lisi");
System.out.println(stu1.getName().hashCode());
System.out.println(stu2.getName().hashCode());
System.out.println(stu1.getName());
System.out.println(stu2.getName());
执行结果:
-323273412
3322003
zhaoliu
lisi
由此可知,虽然两个对象中的String对象在clone后String对象引用相同,但当改变其中一个值的内容后,不会影响另一个对象.
对于数值类型(int,long,float等)拷贝后直接将值赋值给新的对象属性, 对于像String等对象赋值的是对象的属性.
关于深拷贝和浅拷贝问题我没有很透彻的理解, 相关问题请参考 深拷贝和浅拷贝.