简体   繁体   English

Java泛型和数组类型

[英]Java Generics and Array types

Ran into an issue with generics and array types that I am unable to solve. 遇到泛型和数组类型的问题,我无法解决。 It boils down to this. 归结为此。 In the following code, how can I convert a generic List into an Array of the same generic type, while using a factory method ("T convert(String value)") to convert each individual element of the input generic List: 在下面的代码中,如何将通用List转换为相同泛型类型的Array,同时使用工厂方法(“T convert(String value)”)转换输入通用List的每个单独元素:

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

As you can see, my naive approach was to simply use the toArray Method, and cast the result like so: 正如您所看到的,我的天真方法是简单地使用toArray方法,并将结果转换为:

(T) value.toArray()

but this results in a ClassCastException: 但这会导致ClassCastException:

java.lang.ClassCastException: [Ljava.lang.Object; java.lang.ClassCastException:[Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer 无法转换为[Ljava.lang.Integer

Is there a way to solve this that I am not seeing or should I take another approach? 有没有办法解决这个问题,我没有看到或者我应该采取另一种方法?

Edit 编辑

Here's the concrete code that I am trying to fix. 这是我要修复的具体代码。 Specifically the visitArray() method: 具体来说是visitArray()方法:

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

You may use the alternate version of List.toArray that takes as a parameter the type of the array you want to get. 您可以使用List.toArray的备用版本,该版本将您想要获取的数组类型作为参数。

toArray Method toArray方法

You may create an empty array with some method of the Array class. 您可以使用Array类的某个方法创建一个空数组。

Array.newInstance Array.newInstance

So having the expected type you just use Array.newInstance(type, 0); 所以有了预期的类型,你只需使用Array.newInstance(type, 0); and pass in the result to the toArray method. 并将结果传递给toArray方法。

Edit: Since your generic type is an array, you need to get the type of the components, try this: 编辑:由于您的泛型类型是一个数组,您需要获取组件的类型,试试这个:

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

Your value conversion method has a little something I'll let you figure out how to solve :) 你的价值转换方法有一些东西,我会让你弄清楚如何解决:)

Cheers! 干杯!

不要尝试强制转换为T ,尝试强制转换为T[] ,因为您正在处理T的数组。

I suggest ditching the reflection and reference arrays. 我建议抛弃反射和参考数组。

Slightly abusing inheritance: 轻微滥用继承:

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

This works for me: 这对我有用:

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

    }
}

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

no, you have to hard code new Integer[0] 不,你必须硬编码new Integer[0]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM