Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raw types with generic methods independent of the generic type

Tags:

java

generics

This a follow-up to chrert's question Generic classes with Collection getter of other types. If you can come up with a better title to my question, feel free to edit it:

Following code contains a generic class GenericClass<T> with a method of return type T and another method with return type Collection<String>, which is obviously independent of T.

Now, if I instantiate a raw GenericClass (which I would never do, so this question is more a theoretical question, to help understand what's going on) then calling that method in an enhanced for loop won't work, because all generic type information seem to get lost when using raw types. But then, when calling that same method in an assignment, it works (it warns about type unsafety, but it compiles).

In my point of view, either both shouldn't work, or both should work. I don't understand why one works, and the other doesn't. Do you have any hints, or know any parts of the JLS that explain this behavior?

public class GenericClass<T>  {

    T doSomething() {
        return null;
    }

    Collection<String> getCollection() {
        return Collections.emptyList();
    }

    public static void main(String[] args) {
        GenericClass raw = new GenericClass();
        // This will not compile (Error message below)
        for (String str : raw.getCollection()) {
            // Type mismatch: cannot convert from element type Object to String
        }
        // This is only a warning:
        // Type safety: The expression of type Collection needs unchecked conversion to conform to Collection<String>
        Collection<String> coll = raw.getCollection();
        for (String string : coll) {
            // works just fine
        }
    }
}

There is a related question, which, together with the accepted answer here, explains what's going on pretty good: Why won't this generic java code compile?

like image 626
jlordo Avatar asked May 20 '13 18:05

jlordo


Video Answer


1 Answers

In the first case, raw.getCollection() returns a raw Collection. JLS 14.14.2 specifies the type checking for the enhanced for loop:

If Type (in the FormalParameter production) is a reference type, then TargetType is Type; otherwise, TargetType is the upper bound of the capture conversion of the type argument of I, or Object if I is raw.

(emphasis added)

In the second case, you're explicitly assigning a raw type to a generic type, which is allowed with a warning like normal.

like image 180
Louis Wasserman Avatar answered Oct 20 '22 16:10

Louis Wasserman