2012-05-18 74 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如果我是你,我不会不会从那里开始...... –