I am having trouble understanding how type erasure exactly works when collections are involved.
If we look at this code:
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.
}
This example I understand, however this one I could not:
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
}
}
I am unable to understand why exactly 1 is printed. It seemed to me that after type erasure the code will look like this:
void print(Collection c){
System.out.println("1");
}
void print(List l){
System.out.println("2");
}
void printWithClass(List ts){
print(ts);
}
But this is wrong.
It seems to me as if there are two phases of type erasure - one that will turn T to Object, and then one where List<...> will be turned into List.
I don't think it's correct, can someone please explain what is happening here?
Edit: I came up with this guess: The compiler remembers that originally the parameter was List<Number> because it's important for separate compilation. However, it cannot remember that what came in originally to printWithClass was List<Number> as well, it can only know it was List<?>.