赞
踩
在Java编程中,浅拷贝是指在复制对象时,只复制对象的基本数据类型的值和引用类型的地址,**不复制引用类型指向的对象本身。**浅拷贝可以用于一些简单的场景,例如对象的基本属性不包含其他对象的引用类型,或者不需要修改对象引用类型所指向的对象。
说白了就是,基本数据类型和对象(不包括对象里面的属性值,指包括字段)进行复制
以下是几个使用浅拷贝的场景:
class Song {
String title;
String artist;
Song(String title, String artist) {
this.title = title;
this.artist = artist;
}
}
@Data public class Playlist { private Long id; private String name; private List<Song> songs = new ArrayList<>(); public Playlist() { } public void add(Song song){ songs.add(song); } public Playlist(Playlist sourcePlayList) { this.id = sourcePlayList.getId(); this.name = sourcePlayList.getName(); this.songs = sourcePlayList.getSongs(); } }
测试 :
public static void main(String[] args) {
Playlist playlist = new Playlist();
playlist.setId(1L);
playlist.setName("杰伦");
playlist.add(new Song("稻香","杰伦"));
playlist.add(new Song("迷迭香","杰伦"));
playlist.add(new Song("七里香","杰伦"));
// 浅拷贝后的最喜爱的专辑
Playlist favouriteList = new Playlist(playlist);
favouriteList.add(new Song("曹操","林俊杰"));
System.out.println(favouriteList);
}
@Data public class Playlist2 implements Serializable, Cloneable { private Long id; private String name; private List<Song> songs = new ArrayList<>(); public Playlist2() { } public void add(Song song){ songs.add(song); } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { Playlist2 playlist = new Playlist2(); playlist.setId(1L); playlist.setName("杰伦"); playlist.add(new Song("稻香","杰伦")); playlist.add(new Song("迷迭香","杰伦")); playlist.add(new Song("七里香","杰伦")); // 浅拷贝后的最喜爱的专辑 Playlist2 favouriteList = (Playlist2) playlist.clone(); System.out.println(favouriteList); } }
深拷贝的实现,通常有两个思路,一个是递归克隆,一个是使用序列化的手段,我们分别对以下两种方式进行讲解。
class Product implements Cloneable { private String name; private double price; private int stock; // 省略构造函数、getter和setter方法 @Override public Product clone() { try { return (Product) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } } // 促销规则 class PromotionRule implements Cloneable { private String type; private double discount; private Product product; // 省略构造函数、getter和setter方法 @Override protected PromotionRule clone() { try { PromotionRule promotionRule = (PromotionRule) super.clone() Product product = (Product)product.clone(); promotionRule.setProduct(product); return promotionRule; } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } } // 促销活动 class PromotionEvent implements Cloneable { private String name; private Date startDate; private Date endDate; private List<PromotionRule> rules; // 省略构造函数、getter和setter方法 // 在促销活动中的clone方法需要克隆里边所有的非基础数据类型 @Override protected PromotionEvent clone() { try { PromotionEvent clonedEvent = (PromotionEvent) super.clone(); clonedEvent.startDate = (Date) startDate.clone(); clonedEvent.endDate = (Date) endDate.clone(); clonedEvent.rules = new ArrayList<>(); for (PromotionRule rule : rules) { clonedEvent.rules.add(rule.clone()); } return clonedEvent; } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } }
在JDK中,原型设计模式的应用并不非常广泛。然而,在需要快速创建具有相似属性的新对象时,原型设计模式提供
还有一个典型例子,CopyOnWriteArrayList:
public Object clone() {
try {
@SuppressWarnings("unchecked")
CopyOnWriteArrayList<E> clone =
(CopyOnWriteArrayList<E>) super.clone();
clone.resetLock();
// Unlike in readObject, here we cannot visibility-piggyback on the
// volatile write in setArray().
VarHandle.releaseFence();
return clone;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
CopyOnWriteArrayList中的add()
注意跟下面的set()做好区分,因为涉及到扩容,所以原型模式是用不了的,在set()方法里面是用的原型设计模式
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
原来 写时复制技术 的底层之一就是原型设计模式的应用案例
在我们对集合进行修改时,他通过克隆技术,对原数据进行了克隆,原始版本不受影响:
public E set(int index, E element) {
synchronized (lock) {
Object[] es = getArray();
E oldValue = elementAt(es, index);
if (oldValue != element) {
// 克隆
es = es.clone();
es[index] = element;
}
// Ensure volatile write semantics even when oldvalue == element
setArray(es);
return oldValue;
}
}
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。