返回Java中通用类型的数组

时间:2018-10-07 00:45:33

标签: java generics arraylist

我有一个类映射器,该类映射器应该将实现Function接口的任何对象应用于D型数组,并返回R型数组。

问题在于Java不允许我使用“ new R []”,到目前为止,我一直在努力寻找一种从头开始创建R数组的方法。我目前正在尝试使用Array.newInstance方法,但是找不到将R的类类型存储在Class变量中的方法。

public class Mapper {


/**
 * applies passed function to each object of type D in array
 * @param function
 * @param array
 * @return array of type r and length array.length
 */

public static <R, D> R[] map(Function<R, D> function, D[] array)  {

    ArrayList<R> list = new ArrayList<R>();

    //apply function to each variable
    //add rs into object array
    for( int i = 0; i < array.length; i++ ) {

        R r = function.apply( array[i] );
        list.add( r );

    }



    Class<R> clazz = list.get(0).getClass();

    return (R[])Array.newInstance(clazz, list.size()); 

}

}

在运行时如何正确地获得通用类型R的类值,或者以R []的形式返回ArrayList中的对象?

2 个答案:

答案 0 :(得分:0)

您面临的问题与Java泛型类型擦除有关。由于在运行时会擦除所有通用类型,因此Java必须做出权衡以保证类型安全。

通用数组的问题在于Java无法保证类型安全,您可以找到有关此here的很好的示例。简而言之,不允许创建通用数组。

要保留大多数原始代码,可以使用Object[]

public static <D, R> Object[] map(Function<D, R> function, D[] array) {
    List<R> list = new ArrayList<>();
    for (int i = 0; i < array.length; i++) {
        R r = function.apply(array[i]);
        list.add(r);
    }
    return list.toArray(new Object[0]); // no generic array creation allowed!
}

但这就是大多数人坚持使用列表的原因,因为在涉及泛型时使用它们更容易操作:

public static <D, R> List<R> map(Function<D, R> function, List<D> array) {
    List<R> list = new ArrayList<>();
    for (D d : array) {
        list.add(function.apply(d));
    }
    return list;
}

对此的好处是,您仍然可以在知道具体类型之后将其转换为数组:

List<String> strings = List.of("Test1", "Test2");
String[] array = map(String::toLowerCase, strings).toArray(new String[0]);

答案 1 :(得分:0)

最干净的方法是将Class对象传递给函数。另外,似乎您将类型参数的顺序颠倒了Function -第一个类型参数应该是输入类型,第二个应该是结果类型。这样的事情应该使您更接近想要的东西:

public static <R, D> R[] map(Function<D, R> function, D[] array, Class<R> clazz)  {

    R[] result = (R[]) Array.newInstance(clazz, array.length);

    // apply function to each variable and add return value to the result array
    for( int i = 0; i < array.length; i++ ) {
        result[i] = function.apply(array[i]);
    }

    return result;
}

(我还建议将类型参数的顺序反转为您的方法,以与Function之类的内置反射类保持一致。)