2011-11-23 27 views
3

(標題聽起來有點太花哨,但我無法找到匹配的,所以我們希望它是描述性的。)Java的繼承陣列的建設和協變返回

我的代碼工作片如下:

@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

您是否必須避免使用泛型?如果沒有,你不能只是做'Arrays.copyOf'在你的方法中做什麼? –

+0

@ arne.b謹慎地把它放在答案中? ;) – orbfish

回答

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,它可以完全滿足你的需求。

+0

我需要構造一個子類型的數組。如果我在方法返回後試圖向下轉換,我會得到一個ClassCastException。 – orbfish

+0

@orbfish - 更新了我的回答 –

+0

不知道我可以從測試庫中將某些東西放入生產代碼,但我會看一看。 – orbfish

1

爲什麼你不能這樣做: Copyable[] copies = new Copyable[objects.length];? 該行分配了數組,然後您已經使用包含的for循環填充該數組。

+0

我需要構造一個子類型的數組。如果我在方法返回後試圖向下轉換,我會得到一個ClassCastException。 – orbfish

+0

我不知道我明白。副本數組應該能夠容納任何從Copyable下降的東西。你想要做什麼演員? – Chris

+0

Argh我似乎無法編輯自己的帖子....好的,這裏說:MyDO實現可複製。該方法的調用者創建一個MyDO []並將其傳遞給(my)copyOf()。它需要返回並嘗試將其重新轉換回(MyDO)。在這一點上,我會得到一個ClassCastException,因爲新的數組被構造爲新的Copyable []。它需要被構建爲這個爲我工作的子類型。或者我找到了。 – orbfish

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); 
    } 
} 
+0

聰明地抽象我的界面!我知道你不應該混合使用陣列和泛型,但是我必須檢查一下並看一看。 – orbfish

+0

我認爲用泛型,一個甚至不需要ArrayList:'T [] copies =(T [])new Object [objects.length];'和後來'返回拷貝;'沒有投射。 –

+0

我已將代碼更新爲實際可用的內容。它可能會被簡化。但是,您應該能夠將返回的數組用作您的可複製子類型數組之一。 – GriffeyDog

0

大廈GriffeyDog's answersome 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; 
} 
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