(标题听起来有点过于花哨,但我找不到匹配,所以我们希望它是描述性的。)
我有一段如下工作代码:
@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;
}
不像我想的那样漂亮,因为我必须传入数组类,但它适用于我想要它做的事情:分配一个可复制实现者的新数组并使用实现的方法填充它。
我遇到的问题是这是由GWT编译的,它的JRE Emulation库barfs在正确的Java上没有实现。我需要在不调用Arrays.copyOf()的情况下这样做,希望没有反射。
注意:我正在研究clone()版本,但实际上并不想依赖于clone()。我觉得必须有一个更清洁的解决方案。
答案 0 :(得分:2)
这个怎么样:
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
。
修改强>
如果您的可复制对象是可序列化的,则可以序列化然后反序列化数组以创建副本。 gwt-test-utils中有一个实用函数DeepCopy.java,可以完全满足你的需要。
答案 1 :(得分:1)
为什么你不能这样做:
Copyable[] copies = new Copyable[objects.length];
?
该行分配了数组,然后你已经用你所包含的for
循环填充它。
答案 2 :(得分:1)
也许与泛型:
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);
}
}
答案 3 :(得分:0)
在GriffeyDog's answer和some fun I had with generics recently上构建,这是一个没有直接在数组上工作的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;
}
答案 4 :(得分:0)
您可以依靠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
。