Generics / Erasure, or why does it fail?
Hi all,
I've been reading the generics tutorial, http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf, and the chapter on generics in The Java Programming Language, Fourth Edition, and still I can't find anything which explains why the commented line, case 1, in this code fails to compile.
Why doesn't it compile? Does it have anything to do with erasure? Why doesn't the compiler know that E is a subclass of Shape? I've been reading a bit about erasure and thought that E would be replaced with Shape during compilation. The output from javap does also indicate this.
The complete java code:
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
publicclass Aggregator<Eextends Shape>{
private ArrayList<E> elements;
public Aggregator(){
this.elements =new ArrayList<E>();
}
publicvoid add(E e){
elements.add(e);
}
public String toString(){
return elements.toString();
}
publicvoid populateWithTestData(){
//add(new Rectangle());// ## case 1
add((E)new Rectangle());// ## case 2
}
publicstaticvoid main(String[] args){
Aggregator<Rectangle> aggregator =new Aggregator<Rectangle>();
aggregator.add(new Rectangle());// ## case 3 this works fine
}
}
Case 1 does not compile and gives:
The method add(E) in the type Aggregator<E> is not applicable for
the arguments (Rectangle)
Case 2 compiles with a warning, and gives:
Type safety: The cast from Rectangle to E is actually checking
against the erased type Shape
Why does case 3 compile if case 1 doesn't?
Output from javap (Removed output for constructor and toString to reduce the post):
javap -c -classpath . -private -s Aggregator
Compiled from "Aggregator.java"
public class Aggregator extends java.lang.Object{
private java.util.ArrayList elements;
Signature: Ljava/util/ArrayList;
public void add(java.awt.Shape);
Signature: (Ljava/awt/Shape;)V
Code:
0:aload_0
1:getfield#17; //Field elements:Ljava/util/ArrayList;
4:aload_1
5:invokevirtual#28; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
8:pop
9:return
public void populateWithTestData();
Signature: ()V
Code:
0:aload_0
1:new#39; //class java/awt/Rectangle
4:dup
5:invokespecial#41; //Method java/awt/Rectangle."<init>":()V
8:invokevirtual#42; //Method add:(Ljava/awt/Shape;)V
11: return
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
Code:
0:new#1; //class Aggregator
3:dup
4:invokespecial#46; //Method "<init>":()V
7:astore_1
8:aload_1
9:new#39; //class java/awt/Rectangle
12: dup
13: invokespecial#41; //Method java/awt/Rectangle."<init>":()V
16: invokevirtual#42; //Method add:(Ljava/awt/Shape;)V
19: return
}
Does anyone know where I should look to find information on why case 1 doesn't compile? Can anyone explain the problem?
Thanks
Kaj

