引言
有些时候我们需要将java对象内容重写复制一份时(如我们需要将当前记录作废,重新插入一条记录时),可以重写new一个对象,也可以使用clone方法。实现Cloneable接口。
1.浅克隆:是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
public class PersonVO implements Cloneable, Serializable {
private static final long serialVersionUID = 319788853193121606L;
private String personId;
private String name;
private RoleVO roleVO;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
@Test
public void cloneTest() throws CloneNotSupportedException{
PersonVO personVO = new PersonVO();
personVO.setName("person-name");
personVO.setPersonId("123");
RoleVO roleVO = new RoleVO();
roleVO.setName("name");
roleVO.setRoleId("23");
personVO.setRoleVO(roleVO);
PersonVO vo = (PersonVO) personVO.clone();
vo.setName("clone-person-name");
RoleVO rvo = vo.getRoleVO();
rvo.setName("clone-name");
LOGGER.info("personVO {}", personVO);
LOGGER.info("vo {}", vo);
}
//输出结果:
personVO PersonVO(personId=123, name=person-name, roleVO=RoleVO(roleId=23, name=clone-name))
vo PersonVO(personId=123, name=clone-person-name, roleVO=RoleVO(roleId=23, name=clone-name))
2.深度克隆:拷贝了所有,即能够做到原对象和新对象之间完全没有影响。
/**
* 支持深度克隆
* 必要条件
* 1.实现Cloneable,Serializable接口
* 2.重写clone方法
* 3.clone方法改为public
* 4.clone方法必须要支持创建新的对象而不是对象引用
*
*/
@Data
@ToString
public class UserVO implements Cloneable, Serializable {
private static final long serialVersionUID = 4804464826275613486L;
private String userId;
private String password;
private Date date;
private RoleVO roleVO;
@Override
public Object clone() {
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (null != ois) {
ois.close();
}
if (null != oos) {
oos.close();
}
if (null != bos) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
@Test
public void deepCloneTest() {
UserVO userVO = new UserVO();
userVO.setDate(new Date());
userVO.setPassword("123");
userVO.setUserId("12");
RoleVO roleVO = new RoleVO();
roleVO.setName("name");
roleVO.setRoleId("23");
userVO.setRoleVO(roleVO);
UserVO vo = (UserVO) userVO.clone();
vo.setUserId("clone-12");
RoleVO rvo = vo.getRoleVO();
rvo.setName("clone-name");
LOGGER.info("userVO {}", userVO);
LOGGER.info("vo {}", vo);
}
//输出结果:
userVO UserVO(userId=12, password=123, date=Sat Jun 20 17:25:11 CST 2020, roleVO=RoleVO(roleId=23, name=name))
vo UserVO(userId=clone-12, password=123, date=Sat Jun 20 17:25:11 CST 2020, roleVO=RoleVO(roleId=23, name=clone-name))
结果可以看出浅克隆引用修改会相互之间影响,而深度克隆不会。