使用场景:
如果要进行对象clone的话,需要实现Cloneable接口,并调用.clone方法。
实现:
在进行clone的过程中,需要注意如果拷贝的是引用类型的对象(String除外),都是拷贝的地址,而不是拷贝的值。这样做的缺点就是如果改变了克隆的对象的值,被克隆对象的值也会被修改,因为都指向的是同一块堆中的数据。
看一下下面的代码
public class CloneTest implements Cloneable{
private Student student;
private Integer num;
public static void main(String[] args) {
CloneTest cloneTest = new CloneTest();
cloneTest.setNum(1);
Student s = new Student();
s.setName("zhangsan");
s.setSex("nan");
cloneTest.setStudent(s);
try {
CloneTest clone = (CloneTest)cloneTest.clone();
System.out.println(clone.getStudent() == cloneTest.getStudent());
Student student = clone.getStudent();
student.setName("zhangsan-changed");
System.out.println(clone.getStudent().getName());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
}
class Student{
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
输出的结果是
说明student指向的还是同一个对象,所以修改了克隆对象的student,被克隆对象的student也被修改,如果不注意的话,可能就会出现问题。
解决:
为了解决浅克隆出现的问题,可以有以下几种方法:
1 通过json工具类的转换(先转为json字符串,再转回原有类的对象),因为基本上都是通过反射来创建引用对象,即new出来了一个新的对象,所以可以解决。
2 通过序列化,需要类实现Serializable接口,通过io流的方式来实现
//将对象写入流中
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(cloneTest);
//从流中取出
ByteArrayInputStream inputStream = new
ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
CloneTest cloneObj = (CloneTest) objectInputStream.readObject();
System.out.println(cloneObj.getStudent() == cloneTest.getStudent());
也可以使用工具类
byte[] serialize = SerializationUtils.serialize(cloneTest);
CloneTest deserialize = (CloneTest) SerializationUtils.deserialize(serialize);
System.out.println(deserialize.getStudent() == cloneTest.getStudent());
3 手动赋值,将被克隆对象的引用类型的成员变量拿出来,new,并进行手动赋值。