为了账号安全,请及时绑定邮箱和手机立即绑定

在 Java 中返回泛型类型的数组

在 Java 中返回泛型类型的数组

三国纷争 2021-11-03 14:18:49
我有一个类映射器,它应该将实现 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[] 返回?
查看完整描述

2 回答

?
喵喔喔

TA贡献1735条经验 获得超5个赞

最简洁的方法是简单地将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.)保持一致。)


查看完整回答
反对 回复 2021-11-03
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

您面临的问题与 Java 泛型类型擦除有关。由于所有泛型类型都在运行时被擦除,Java 必须进行权衡以保证类型安全。


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


要保留大部分原始代码,您可以使用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]);


查看完整回答
反对 回复 2021-11-03
  • 2 回答
  • 0 关注
  • 262 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信