克服Java中的类型擦除

克服Java中的类型擦除,java,generics,type-erasure,Java,Generics,Type Erasure,我有一个无法更改的客户端类 List<Integer> list1= Arrays.asList(1,2,3); System.out.println("Total sum is:"+sum(list1)); printlist(list1); List<Double> list2=Arrays.asList(1.0,2.0,3.0); System.out.println("Total sum is:"+sum(list2)); printlist(list2); 我

我有一个无法更改的客户端类

List<Integer> list1= Arrays.asList(1,2,3);
System.out.println("Total sum is:"+sum(list1));
printlist(list1);
List<Double> list2=Arrays.asList(1.0,2.0,3.0);
System.out.println("Total sum is:"+sum(list2));
printlist(list2);
我这里有商业逻辑

private static Object sum(List<? extends Number> list) {
    double sum = 0;
    for (Number i: list) {
        sum+=i.doubleValue();
    }     
    return sum;
}
所以我想返回6表示整数,返回6.0表示双精度。我该怎么做?我想根据类型将sum类型转换为int或double,但由于类型擦除,所有信息都丢失了。有人能帮我吗

使用“instanceof”

     if( i instanceof Double) {
       System.out.println("param is a Double");
     }
     else if( i instanceof Integer) {
       System.out.println("param is an Integer");
    }

列表中的对象在运行时仍具有与其关联的类型信息。唯一删除的类型是泛型类型,即示例中的列表。泛型在编译时被检查,但不会在生成的字节码中维护。这意味着您可以使用instanceof检查集合的内容:

private static Object sum(List<? extends Number> list) {
    Integer integerSum = 0;
    Double doubleSum = 0.0;
    boolean hasDouble = false;
    for (Number i: list) {
        if (i instanceof Integer) {
            integerSum += i.intValue();
        } else {
            doubleSum += i.doubleValue();
            hasDouble = true;
        }
    }
    if (hasDouble)
        return doubleSum + integerSum;
    return integerSum;
}

代码有一些处理混合列表的特性,并且不能正确处理长、短、字节等。

假设数字子类实例可以用double表示是危险的。为了安全地执行此操作,您需要检查所有可能的类型

@SuppressWarnings("unchecked")
private static <T extends Number> T sum(List<T> list) {
    Objects.requireNonNull(list);

    if (list.isEmpty() || list.contains(null))
        throw new IllegalArgumentException();

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

    if (clazz == Integer.class) {
        return (T) (Integer) list.stream().mapToInt(i -> (Integer) i).sum();
    }
    else if (clazz == Double.class) {
        return (T) (Double) list.stream().mapToDouble(i -> (Double) i).sum();
    }
    /* And other Number subclass types */

    // Not possible if all types covered
    throw new IllegalStateException();
}

问题/答案是否与此相关。

如果是整数和双精度的混合,该怎么办?现在我不检查该条件。我只是想理解泛型。我是泛型的新手除了检查列表的内容之外,没有办法找出它是什么类型的列表。因此,您可以更改“业务逻辑”方法?您可以使用覆盖,即使java也可以,您不需要调用双构造函数。只需返回doubleSum+integerSum。您可以使用double对所有值求和,并在末尾强制转换它。