1. PROS&CONS
PROS
- 对象拷贝比new实例性能高
- 简化创建过程
这是因为对象拷贝的过程时,不会调用构造器,通过实现Cloneable
接口并调用Object.clone
实现对象拷贝。
CONS
- 必须重写
Object.clone
- 复杂对象进行对象拷贝的风险大,涉及深拷贝,浅拷贝问题
2. 适用场景
- 类初始化消耗较多资源,循环体生产大量对象时
- new一个对象过程繁琐,构造函数负债
3. 浅拷贝&深拷贝
浅拷贝
@Setter
@Getter
public class User implements Cloneable {
private String id;
private String username;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", birthday=" + birthday +
'}' + super.toString();
}
}
user1通过对象拷贝获得user2实例对象,但是user2中的birthday和user1中的birthday指向都了堆中的同一个Date
实例对象,即相同引用,属于浅拷贝。这样会导致无论是在user1修改了birthday还是user2修改,birthday都会发生变化。
public static void main(String[] args) throws CloneNotSupportedException {
Date date1 = new Date(1L);
User user1 = new User();
user1.setBirthday(date1);
User user2 = (User) user1.clone();
log.info("{}", user1);
log.info("{}", user2);
user2.getBirthday().setTime(new Date().getTime());
log.info("{}", user1);
log.info("{}", user2);
}
深拷贝
如何实现深拷贝?通过重现User类的clone方法。
@Override
protected Object clone() throws CloneNotSupportedException {
User user = (User) super.clone();
// 深克隆
user.birthday = (Date) user.getBirthday().clone();
return user;
}
4. 原型模式破坏单例模式
HungrySingleton hungrySingleton = HungrySingleton.getInstance();
Method method = hungrySingleton.getClass().getDeclaredMethod("clone");
method.setAccessible(true);
HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton, null);
log.info("{}", hungrySingleton);
log.info("{}", cloneHungrySingleton);
如何解决?
- 单例类不实现
Cloneable
-
clone
方法返回原单例对象
@Override
protected Object clone() throws CloneNotSupportedException {
return getInstance();
}
5. 源码案例
- ArrayList
- HashMap
- Mybatis#CacheKey
网友评论