Could someone please explain to me why there is explicit need to assign generic type for ForEachLoop instance?
Why compiler complains: Type mismatch: cannot convert from element type Object to String?
JDK 1.5.0_09
import java.util.ArrayList;
import java.util.Collection;
public class ForEachLoop<T> {
public static void main(String[] args) {
// Non functional version
ForEachLoop f = new ForEachLoop();
// Functional version
//ForEachLoop<Integer> f = new ForEachLoop();
// Type mismatch: cannot convert from element type Object to String
for(String a : f.getStrings()) {
System.out.println(a);
}
}
public Collection<String> getStrings() {
Collection<String> strings = new ArrayList<String>();
strings.add("Hello");
return strings;
}
}
This is a rather common mistake:
should be
If you use the raw type (which you shouldn’t) the compiler will erase all generic information for that instance even if it’s not the type parameter T, to make it compatible with pre 1.5 code.
Only use raw types if you’re writing for Java 1.4 or less, in which case you shouldn’t have any generics whatsoever. At the bytecode level the method returns a Collection (raw) after type erasure. Normally, if the instance has the generic type set, when you try to do
geton the collection, the compiler will use the generic information to decide that it should return a String, and then at the bytecode level it automatically casts the Object it receives from the Collection to String (since it’s guaranteed to be a String). But if you use the raw type the compiler will ignore all generic information and will not automatically cast the object for you anymore.Edit: In the section on Raw Types there are these things:
Notice that the Inner class has it’s own type parameter independent of the one of the Outer class, and it still gets erased. Basically they don’t want us mixing raw and generic types on the same instance, since it doesn’t make sense in any version (in pre 1.5, the generic part will be an error, in 1.5+ the raw type is discouraged, and may even be removed from future versions)
Then there’s also this:
which says that constructors, instance methods and non-static fields will be treated as raw in a raw instance. Static members will be treated as generic anyway, since they don’t require an instance to be accesed.