简体   繁体   English

如何将通用ArrayList强制转换为通用数组

[英]How to cast a Generic ArrayList to a Generic Array

When I call printArray in my pvsm, the error I keep receiving is: 当我打电话printArray在我pvsm,错误我不断收到的是:

Exception in thread "main" java.lang.ClassCastException: 
    java.base/[Ljava.lang.Object; cannot be cast to java.base/[Ljava.lang.Integer

I know the problem is with the R[] result = (R[]) list.toArray() . 我知道问题出在R[] result = (R[]) list.toArray() I have no idea how to convert the ArrayList to an array and cast it to a generic at the same time. 我不知道如何将ArrayList转换为数组并将其同时转换为泛型。 Note I cannot change the parameters of the function map or add any new functions. 注意:我无法更改功能map的参数或添加任何新功能。

public class Homework2 {

    public static void main(String[] args){
        Function<Integer,Integer> function = new CalculateSuccessor();
        Double[] d= {2.0,4.0,8.0};
        Integer[] i= {2,4,8};
        printArray(map(function,i));
    }

    @SuppressWarnings("unchecked")
    public static <R,D> R[] map(Function<R,D> function, D[] array){
        ArrayList<R> list = new ArrayList<>();
        for (D element: array){
           list.add(function.apply(element));
        }


        // THIS LINE OF DAMN CODE
        R[] result = (R[]) list.toArray();

        return result;
    }

    public static <R> void printArray(R[] array){
        System.out.print("{ ");
        for (R element: array){
            System.out.print(element + ", ");
        }
        System.out.print("}");
    }

    public static class CalculateSuccessor implements Function<Integer,Integer> {
        @Override
        public Integer apply(Integer parameter) {
            return parameter * 2;
        }
    } //End CalcSuc

} //End Homework2

In another class I have 在另一堂课上

public interface Function<R,D> {
     public R apply(D parameter);
}

which you need for the function.apply. 您需要的function.apply。 My professor insisted we use this instead of importing Function. 我的教授坚持认为我们使用此函数而不是导入Function。

Part one, you need the Class<R> in order to dynamically create an array R[] . 第一部分,您需要Class<R>才能动态创建数组R[] I would prefer Arrays.toString over implementing my own version of that. 与实现自己的版本相比,我更喜欢Arrays.toString I also needed a Function<D, R> (not a Function<R, D> ). 我还需要一个Function<D, R> (不是Function<R, D> )。 But making those changes like 但是进行这些更改

public static void main(String[] args) {
    Function<Integer, Integer> function = new CalculateSuccessor();
    Double[] d = { 2.0, 4.0, 8.0 };
    Integer[] i = { 2, 4, 8 };
    System.out.println(Arrays.toString(map(Integer.class, function, i)));
}

public static <R, D> R[] map(Class<R> cls, Function<D, R> function, D[] array) {
    ArrayList<R> list = new ArrayList<>();
    for (D element : array) {
        list.add(function.apply(element));
    }
    return list.toArray((R[]) Array.newInstance(cls, list.size()));
}

I get 我懂了

[4, 8, 16]

You can extract the type information from the Function<D,R> because you implemented it with an actual class. 您可以从Function<D,R>提取类型信息Function<D,R>因为您是通过实际的类实现的。 So together with @Elliott Frisch answer. 因此,与@Elliott Frisch一起回答。

public static <R, D> R[] map(Function<D, R> function, D[] array) {
    ArrayList<R> list = new ArrayList<>();
    for (D element : array) {
        list.add(function.apply(element));
    }
    Class<?> componentClass = extractReturnType(function)
    return list.toArray((R[]) Array.newInstance(componentClass, list.size()));
}

private static Class<?> extractReturnType(Function<?, ?> function) {
    Type[] interfaces = function.getClass().getGenericInterfaces();
    for(Type iface:interfaces) {
        if (iface instanceof ParameterizedType && Function.class.equals(((ParameterizedType) iface).getRawType())) {
            return (Class<?>) ((ParameterizedType) iface).getActualTypeArguments()[1];
        }
    }
    throw new IllegalArgumentException("Unable to extract type information");
}

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

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