如何删除通用列表类型?当我自己尝试时,会出错

时间:2017-02-09 16:00:23

标签: java generics

我试图找出以下方法是如何删除类型的

public class Util {
    public static <T extends Number> int sum(List<T>list){
        int sum=0;
        for(Number n:list){
            sum+=n.intValue();
        }
        return sum;
    }
}

我读到类型参数被第一个绑定替换。 所以我尝试了,但得到了一个错误:

public static int sum3(List list){
    int sum=0; 
    for(Number n:list){         <- Type mismatch: cannot convert from element type Object to Number
        sum+=n.intValue();
    }
    return sum;
}

2 个答案:

答案 0 :(得分:1)

你的第二个代码实际上并不是类型擦除后的等效代码。它可能是,因为,正如您所发现的,增强的for循环不会编译。

如果你查阅language spec,它会显示增强for循环的等效基本for循环:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    {VariableModifier} TargetType Identifier =
        (TargetType) #i.next();
    Statement
}

这实际上是 执行的内容:增强的for循环只是基本for循环的语法糖,看起来像这样。

所以,编译器对你的第一个代码做的第一件事就是&#34; desugar&#34;它来:

public static <T extends Number> int sum(List<T>list){
  int sum=0;
  for (Iterator<Number> i = list.iterator(); i.hasNext(); ) {
    Number n = (Number) i.next();
    sum += n.intValue();
  }
  return sum;
}

然后,当应用类型擦除时,它将重写为:

public static int sum(List list){
  int sum=0;
  for (Iterator i = list.iterator(); i.hasNext(); ) {
    Number n = (Number) i.next();
    sum += n.intValue();
  }
  return sum;
}

请注意,唯一不同的是i.next()在第一种情况下是Number,因此不需要演员;但是在第二个中是Object(因为原始迭代器),所以演员是必要的。

这种形式的类型擦除代码编译。实际上,如果您尝试反编译此版本的代码,您将看到它的字节码与OP的问题中的第一个代码相同。

当然,正如Sotirios指出问题是What is a raw type and why shouldn't we use it?的问题,你不应该尝试自己进行类型擦除。但知道它在做什么是很有用的。

答案 1 :(得分:0)

在编译器的类型检查阶段之后发生擦除。 最终,它会导致您编写的内容,但首先会进行类型检查。