I got a strange compiler error when using generics within a for-each loop in Java. Is this a Java compiler bug, or am I really missing something here?
Here is my whole class:
public class Generics<T extends Object> {
public Generics(T myObject){
// I didn't really need myObject
}
public List<String> getList(){
List<String> list = new ArrayList<String>();
list.add("w00t StackOverflow");
return list;
}
public static void main(String...a){
Generics generics = new Generics(new Object());
for(String s : generics.getList()){
System.out.println(s);
}
}
}
The compiler is complaining about the line with the for-each: "Type mismatch cannot convert from element type Object to String."
If I make this subtle change, it compiles:
public static void main(String...a){
Generics<?> generics = new Generics(new Object());
for(String s : generics.getList()){
System.out.println(s);
}
}
I know getList()
does use generics, but it uses them in what I thought was a completely unrelated way. I could understand this if I were trying to iterate over something of type T and getList()
returned a List<T>
or something, but that's not the case here. The return type of getList()
should have absolutely nothing to do with T and shouldn't care whether I use the raw type for my Generics object or not...right? Shouldn't these be completely unrelated, or am I really missing something here?
Note that the code also compiles if I do this, which I thought should have been equivalent to the first as well:
public static void main(String...a){
Generics generics = new Generics(new Object());
List<String> list = generics.getList();
for(String s : list){
System.out.println(s);
}
}
<T extends Object>
is no different than<T>
. You are not making a generic version of you class, you are making the raw type. Which brings us to the question of why is your class generic in the first place? The only place you use T is in the constructor and you don't use that reference. – Constrictor<T extends Object>
because I just needed something for an example. The real code obviously is something else, and it does use T...it just uses T in a way completely unrelated togetList()
. – Proudlove<T extends *something*>
without putting the focus on what that something was, so I pickedObject
for my example. – Proudlove