有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java泛型和数组类型

遇到了我无法解决的泛型和数组类型问题。归结起来就是这样。在下面的代码中,如何将泛型列表转换为相同泛型类型的数组,同时使用工厂方法(“T convert(String value)”)转换输入泛型列表的每个元素:

@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;
    }
}

如您所见,我的天真方法是简单地使用toArray方法,并按如下方式转换结果:

(T) value.toArray()

但这会导致ClassCastException:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer

有没有办法解决我没有看到的问题,或者我应该采取另一种方法

编辑

下面是我试图修复的具体代码。特别是visitArray()方法:

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


共 (5) 个答案

  1. # 1 楼答案

    您可以使用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);
    

    您的值转换方法有一点我将让您了解如何解决:)

    干杯

  2. # 2 楼答案

    不要试图强制转换到T,尝试强制转换到T[],因为您正在处理一个t的数组

  3. # 3 楼答案

    这对我很有用:

    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;
            }
    
        }
    }
    
  4. # 4 楼答案

    return (T) values.toArray();应该是return (T)output.toArray( new Integer[0])

    不,你必须硬编码new Integer[0]

  5. # 5 楼答案

    我建议抛弃反射和参考阵列

    轻微滥用遗产:

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