最近發現了一個現象:用BeanUtils.copyProperties(Object source, Object target)
時, 如果source和target中有List
物件,然後修改了source的List
物件中的元素,發現target的List
物件也會跟著變化。
調研了
BeanUtils.copyProperties(Object source, Object target)
原始碼,發現是通過method.invoke
方法來實現屬性的copy的,所以物件的屬性複製都是淺Copy。
於是乎就換了一個種方式來寫:
List<A> source = new ArrayList<>();
source.add(new A());
List<A> copy = new ArrayList<>(source);
複製程式碼
發現居然還是不行!
覺得很奇怪,然後看了ArrayList
的構造方法,
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
複製程式碼
elementData = c.toArray()
這段程式碼還是淺Copy。
思考了一會,難道只能通過遍歷元素,然後新增元素的方式來解決嗎?抱著疑問去Google了下,發現該函式Collections.copy
解決了問題,進入其原始碼發現是在遍歷元素然後再新增。。。
總結
- copy完之後,一般都是直接返回給呼叫方了,一般不會再次運算元據,這樣就不會引發淺Copy的問題。這也是copy的正確用法。