在使用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)