Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over member typed collection fails when using untyped reference to generic object [duplicate]

Tags:

java

generics

Possible Duplicate:
Generics in for each loop problem if instance does not have generic type assigned

Could someone clarify why iterate1() is not accepted by compiler (Java 1.6)? I do not see why iterate2() and iterate3() are much better.

import java.util.Collection;
import java.util.HashSet;

public class Test<T> {

    public Collection<String> getCollection() {
        return new HashSet<String>();
    }

    public void iterate1(Test test) {
        for (String s : test.getCollection()) {
            // ...
        }
    }

    public void iterate2(Test test) {
        Collection<String> c = test.getCollection();
        for (String s : c) {
            // ...
        }
    }

    public void iterate3(Test<?> test) {
        for (String s : test.getCollection()) {
            // ...
        }
    }


}

Compiler output:

$ javac Test.java
Test.java:11: incompatible types
found   : java.lang.Object
required: java.lang.String
  for (String s : test.getCollection()) {
                                              ^
Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
like image 846
Alexander Pavlov Avatar asked Oct 02 '12 15:10

Alexander Pavlov


1 Answers

When you use a raw type (e.g. Test rather than Test<T>, the compiler treats it (JLS 4.8) as the erasure of that type (JLS 4.6) - that erases generics completely, whether they use the type parameter or not:

The type parameters of a constructor or method (§8.4.4), and the return type (§8.4.5) of a method, also undergo erasure if the constructor or method's signature is erased.

Basically, the use of a raw type is treated by the compiler as an indication that you don't want that code to be aware of generics at all - so the method signature is erased to:

public Collection getCollection()

... hence the compile-time error, as the inferred element type is Object, as per JLS 14.14.2.

like image 190
Jon Skeet Avatar answered Nov 15 '22 09:11

Jon Skeet