(标题听起来有点花哨,但我找不到匹配的,所以我们希望它是描述性的。)
我有一段工作代码,如下所示:
@SuppressWarnings("unchecked")
public static Copyable[] copyOf(Copyable[] objects, Class type) {
Copyable[] copies = Arrays.copyOf(objects, objects.length, type);
for( int i=0; i < copies.length; ++i ) {
if( objects[i] == null )
throw new IllegalArgumentException("Copyable[] contains null reference", new NullPointerException());
copies[i] = objects[i].copy();
}
return copies;
}
不像我想的那么漂亮,因为我必须传入数组类,但它可以做我想做的事情:分配一个Copyable实现者的新数组,并使用实现的方法填充它。
我遇到的问题是,这是由GWT编译的,它的JRE仿真库禁止正确的Java,它没有实现。我需要在不调用Arrays.copyOf()的情况下做到这一点,并且希望没有反射。
注意:我正在使用clone()版本,但也不想依赖clone()。我觉得一定有一个更干净的解决方案。
这个怎么样:
public static Copyable[] copyOf(Copyable[] objects) {
Copyable[] copies = new Copyable[objects.length];
for( int i=0; i < copies.length; ++i ) {
if( objects[i] == null )
throw new IllegalArgumentException("Copyable[] contains null reference", new NullPointerException());
copies[i] = objects[i].copy();
}
return copies;
}
在复制元素本身之前,不需要将objects
数组实际复制到copies
中。
编辑
如果你的Copyable对象是可序列化的,你可以只序列化,然后反序列化数组来创建一个副本。在gwt-test-utils中有一个实用程序函数DeepCopy.java,它可以完全满足您的需求。
你为什么不能这样做:Copyable[] copies = new Copyable[objects.length];
吗?这一行分配数组,然后您已经用您包含的for
循环填充它。
可能使用泛型:
public interface Copyable<T> {
T copy();
}
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class Test {
static class My implements Copyable<My> {
int x;
public My copy() {
My my = new My();
my.x = this.x;
return my;
}
}
@SuppressWarnings("unchecked")
public static <T extends Copyable<T>> T[] copyOf(T[] objects, Class<T> type) {
List<T> copies = new ArrayList<T>();
for (int i = 0; i < objects.length; ++i) {
if (objects[i] == null) throw new IllegalArgumentException("Copyable[] contains null reference",
new NullPointerException());
copies.add((T) objects[i].copy());
}
T typeVar = null;
try {
typeVar = (T) Class.forName(type.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object t = Array.newInstance(typeVar.getClass(),0);
return copies.toArray((T[])t);
}
public static void main(String[] args) {
My[] stuff = new My[1];
My elem = new My();
elem.x = 1;
stuff[0] = elem;
My[] copies = copyOf(stuff, My.class);
System.out.println(copies[0].x);
}
}
基于GriffeyDog的回答和我最近对泛型的一些乐趣,这里是一个没有Class
对象的解决方案,直接在数组上工作:
@SuppressWarnings("unchecked")
public static <T extends Copyable> T[] copyOf(T[] objects) {
T[] copies = (T[]) new Object[objects.length];
for (int i = 0; i < copies.length; ++i) {
if (objects[i] == null)
throw new IllegalArgumentException(/*...*/);
copies[i] = (T) objects[i].copy();
}
return copies;
}
您可以对数组本身使用clone()
,然后对每个对象使用copy()
:
@SuppressWarnings("unchecked")
public static Copyable[] copyOf(Copyable[] objects) {
Copyable[] copies = (Copyable[]) objects.clone();
for( int i=0; i < copies.length; ++i ) {
if( objects[i] == null )
throw etc;
copies[i] = objects[i].copy();
}
return copies;
}
每个数组都实现了clone()方法,该方法返回数组的浅拷贝。所以我认为它足够干净,可以满足你的需要。
注意,这样,您也不需要参数Class type
。