【问题标题】:Returning an Array of a Generic Type in Java在 Java 中返回一个泛型类型的数组
【发布时间】:2019-03-12 01:53:07
【问题描述】:

我有一个类映射器,它应该将任何实现 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 正确获取类值,或者以其他方式将 ArrayList 中的对象作为 R[] 返回?

【问题讨论】:

  • 这应该是重复的,但无论如何我都会添加一个答案,以举例说明如何改进代码。
  • 我可能应该提到 - 分配必须尊重方法签名。这就是我遇到麻烦的原因。
  • 这没有意义,请看我的回答。

标签: java generics arraylist


【解决方案1】:

您面临的问题与 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]);

【讨论】:

    【解决方案2】:

    最简洁的方法是简单地将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 等内置反射类保持一致。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2022-10-14
      • 2014-05-16
      相关资源
      最近更新 更多