当涉及到集合时,我很难理解类型擦除是如何工作的。
如果我们看一下这个代码:
static void print(Object o){
System.out.println("Object");
}
static void print(String s){
System.out.println("String");
}
static void print(Integer i){
System.out.println("Integer");
}
static <T> void printWithClass (T t)
print(t);
}
public static void main(String[] args){
printWithClass("abc") //String is printed, because T turns to Object after type erasure.
}我理解这个例子,但是这个我不能理解:
class Printer<T>{
void print(Collection<?> c){
System.out.println("1");
}
void print(List<Number> l){
System.out.println("2");
}
void printWithClass(List<T> ts){
print(ts);
}
}
public class Main
{
public static void main(String[] args){
Printer<Integer> printer=new Printer<>();
printer.printWithClass(new ArrayList< Integer>()); //1 is printed
}
}我不明白为什么要打印1。在我看来,在类型删除之后,代码将如下所示:
void print(Collection c){
System.out.println("1");
}
void print(List l){
System.out.println("2");
}
void printWithClass(List ts){
print(ts);
}但这是不对的。
在我看来,类型擦除有两个阶段--一个阶段将T变为对象,然后一个阶段将List<...>转化为List。
我不认为这是正确的,谁能解释一下这里发生了什么吗?
编辑:我想出了一个猜想:编译器记得最初的参数是List<Number>,因为它对于单独编译很重要。然而,它不记得最初进入printWithClass的也是List<Number>,它只能知道它是List。
发布于 2021-03-14 22:08:55
请记住,方法重载是在编译时解析的(与将在运行时解决的重写方法相反)。
这意味着在编译printWithClass时必须执行调用特定方法签名的决定。这也意味着此时不执行类型擦除(因为擦除是运行时的属性,编译器仍然关心所有类型参数)。
在这种方法中:
void printWithClass(List<T> ts){
print(ts);
}由于T是完全无界的(即它可能是任何引用类型),那么只有一个可能的print方法可以调用,那就是接受Collection<?>的方法,因为我们不知道T是Number。
另外,由于List<Integer> 不是a List<Number>,即使这些规则不同,您的main方法也不能导致调用其他print方法。
https://stackoverflow.com/questions/66629648
复制相似问题