2012-05-18 73 views
4

遇到了我無法解決的泛型和數組類型問題。歸結到這一點。在下面的代碼中,如何將通用列表轉換爲具有相同通用類型的數組,同時使用工廠方法(「T convert(String value)」)來轉換輸入通用列表中的每個單獨元素:Java泛型和數組類型

@Test 
public void test(){ 
    List<String> integers = Arrays.asList("1", "2", "3", "4"); 

    Integer[] integerArray = new TypeConverter<Integer[]>(Integer[].class).convert(integers); 

    assertEquals(4, integerArray.length); 
    assertEquals(1, integerArray[0].intValue()); 
    assertEquals(2, integerArray[1].intValue()); 
    assertEquals(3, integerArray[2].intValue()); 
    assertEquals(4, integerArray[3].intValue()); 
} 

public class TypeConverter<T>{ 
    Class<T> type; 

    public TypeConverter(Class<T> type) { 
     this.type = type; 
    } 

    T convert(List<String> values){ 

     List output = new ArrayList(); 

     for (String value : values) { 
      //have to use Object.class here since I cant get the non-array type of T: 
      output.add(new TypeConverter(type.getComponentType()).convert(value)); 
     } 

     return (T) output.toArray(); 
    } 

    T convert(String value){ 
     //convert to an int; 
     if(type == Integer.class){ 
      return (T) new Integer(Integer.parseInt(value)); 
     } 
     return null; 
    } 
} 

正如你看到的,我天真的做法是簡單地使用指定者的方法,並把結果像這樣:

(T) value.toArray() 

但這會導致一個ClassCastException:

的java.lang .ClassCastException:[L java.lang.Object繼承;不能投到[Ljava.lang.Integer

有沒有辦法解決這個問題,我沒有看到,或者我應該採取另一種方法?

編輯

這裏,我試圖解決具體的代碼。具體的visitArray()方法:

https://github.com/johncarl81/transfuse/blob/master/transfuse/src/main/java/org/androidtransfuse/analysis/adapter/AnnotationTypeValueConverterVisitor.java

+0

可能重複[?List類的指定者:Java的,爲什麼我不能的「整數」列表轉換成「整數」陣列(HTTP://計算器.COM /問題/ 7281793 /列表班組長-指定者功能於Java的,爲什麼-着-I-轉換-A-列表的整數到一個-INT) –

+0

其實我提交我的職務之前閱讀該文章。我的問題不是重複的,因爲我在詢問有關數組的泛型。 –

回答

2

您可以使用的List.toArray替代版本,作爲一個參數,你想要得到的陣列的類型。

toArray Method

您可以創建與Array類的一些方法空數組。

Array.newInstance

因此具有預期的類型,你只需要使用Array.newInstance(type, 0);和結果傳遞給toArray方法。

編輯: 由於您的泛型類型是一個數組,你需要獲得部件的類型,試試這個:

Object[] array = (Object[]) Array.newInstance(type.getComponentType(), 0); 
return (T) output.toArray(array); 

你的價值轉換方法有一個小東西,我會讓你找出如何解決:)

乾杯!

+0

我會傳入toArray()方法? –

+0

我會在編輯中加入它,你去! –

+0

return(T)output.toArray(Array.newInstance(type,0));不編譯。 Arraay.newInstance(類型,0)返回Object類型和List.toArray()需要一個數組類型T [] –

2

不要試圖投到T,試着轉換爲T[],因爲您正在處理T的數組。

+0

這是一種可能性,但我試圖瞄準更普遍的解決方案。 –

0

return (T) values.toArray();應該return (T)output.toArray(new Integer[0])

沒有,你要硬編碼new Integer[0]

+0

我怎麼能做到這一點的基礎的類型T或類類型? –

+0

Java的泛型不能做到這一點,你看連的Java API做花樣,比如'指定者(新的整數[0])'。 –

+0

在這個人爲設計的例子中,這種硬編碼方法可行,但我需要一個更通用的解決方案。 –

1

這個工作對我來說:

import java.util.*; 
import java.lang.reflect.*; 

public class Foo { 
    public static void main(String[] args) { 
     new Foo().test(); 
    } 

    public void test(){ 
     List<String> integers = Arrays.asList("1", "2", "3", "4"); 

     Integer[] integerArray = new TypeConverter<Integer>(Integer.class).convert(integers); 

     System.out.println(Arrays.deepToString(integerArray)); 

    } 

    public class TypeConverter<T>{ 
     Class<T> type; 

     public TypeConverter(Class<T> type) { 
      this.type = type; 
     } 

     T[] convert(List<String> values){ 

      List<T> output = new ArrayList<>(); 

      for (String value : values) { 
       output.add(convert(value)); 
      } 

      return output.toArray((T[]) Array.newInstance(type, output.size())); 
     } 

     T convert(String value){ 
      if(type == Integer.class){ 
       return (T) new Integer(Integer.parseInt(value)); 
      } 
      else if(type == Long.class){ 
       return (T) new Long(Long.parseLong(value)); 
      } 
      return null; 
     } 

    } 
} 
+0

與@Hidde的建議非常相似。 –

+0

你可以從我加入到這個問題的具體的例子看,我沒有對的TypeConverter(AnnotationTypeValueConverterVisitor)的返回類型控制,其實我只是實現一個接口。建議? –

2

我建議拋棄的反射和參考陣列。

略濫用繼承:

public abstract class StringConverter<T> { 

    public List<T> convert(List<String> values) { 
     List<T> output = new ArrayList<>(); 
     for (String value : values) { 
      output.add(convert(value)); 
     } 
     return output; 
    } 

    public abstract T convert(String value); 
} 

public static StringConverter<Integer> toInteger() { 
    return new StringConverter<>() { 
     public Integer convert(String value) { 
      return Integer.parseInt(value); 
     } 
    }; 
} 
+0

這是一個甜蜜的解決方案。而且,對於所有你想要處理的類型,必須有一個'if(/ else)'大的'convert()'例程。 – QuantumMechanic

+0

Tom,這是我的問題,我無法控制方法的返回類型,因爲我正在實現一個接口。下面是相關的代碼:https://github.com/johncarl81/transfuse/blob/master/transfuse/src/main/java/org/androidtransfuse/analysis/adapter/AnnotationTypeValueConverterVisitor.java –

+0

@johncarl如果我是你,我不會不會從那裏開始...... –