我试图找出以下方法是如何删除类型的
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;
}
答案 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)
在编译器的类型检查阶段之后发生擦除。 最终,它会导致您编写的内容,但首先会进行类型检查。