在使用org.apache.commons.lang.ArrayUtils進行數組拷貝的時候,發現其只能實現數組的淺拷貝,而且不支持泛型
經過改造,我自己重新實現了數組的深拷貝,同時支持多重數組拷貝。
因爲Object的clone方法聲明成protected,在使用泛型的時候,無法調用clone方法,所以我們自己重新定義個克隆的接口
package demo;
public interface MyCloneable {
<T> T cloneObject();
}
再定義一個我們要使用的類,實現這個接口,實現對象的深拷貝
package demo;
import lombok.*;
@Getter
@Setter
@ToString
@RequiredArgsConstructor(staticName = "of")
public class MyObject implements MyCloneable{
@NonNull
String name;
@Override
public MyObject cloneObject() {
//返回一個新的MyObject對象出來,相當於new MyObject()
return MyObject.of(name);
}
}
最後就是複製數組的代碼,在這裏使用泛型,以保證克隆前後數組類型不變
public static <T> T[] cloneArray(T[] array) {
if (array == null) {
return null;
}
T[] newArr = array.clone();
//找到數組中一個非空元素的下標
int nonNullIndex = findNonNullIndex(newArr);
if(nonNullIndex<0)
return newArr;
if(newArr[nonNullIndex].getClass().isArray()){ //如果元素是數組,那對每個元素進行數組拷貝
if (newArr.length > 0) {
for (int i = 0; i < newArr.length; i++) {
newArr[i] = (T) cloneArray((Object[]) newArr[i]);
}
}
}else if(newArr[nonNullIndex] instanceof MyCloneable) { //如果元素實現了克隆接口,則對每個元素進行手動克隆,實現深克隆
if (newArr.length > 0) {
for (int i = 0; i < newArr.length; i++) {
if(newArr[i]!=null)
newArr[i] = ((MyCloneable)array[i]).cloneObject();
}
}
}
return newArr;
}
private static <T> int findNonNullIndex(T[] array){
if(array==null)
return -1;
for(int i=0;i<array.length;i++){
if(array[i]!=null)
return i;
}
return -1;
}
測試一下代碼
//ArrayUtils.clone()克隆數組,數組是新的,但是數組中的元素還是原來的對象
//重寫的clone可以進行深拷貝
MyObject[] myObjects = new MyObject[3];
myObjects[0] = MyObject.of("a");
MyObject[] myObjects1 = cloneArray(myObjects);
myObjects1[0].setName("1");
System.out.println();
Arrays.asList(myObjects).forEach(System.out::println);
Arrays.asList(myObjects1).forEach(System.out::println);
MyObject[][] myObjects2 = new MyObject[2][2];
myObjects2[0] = new MyObject[2];
myObjects2[0][1] = MyObject.of("01");
MyObject[][] myObjects3 = cloneArray(myObjects2);
myObjects3[0][1] = MyObject.of("aa");
System.out.println();
System.out.println(myObjects2[0][1]);
System.out.println(myObjects3[0][1]);
最後的結果
MyObject(name=a)
null
null
MyObject(name=1)
null
null
MyObject(name=01)
MyObject(name=aa)