AnAmuser
AnAmuser

Reputation: 1895

Java Generics and return types

I just ran into something that I do not understand. Why isn't the for each loop below legal when the second identically one is?

public interface SomeInterface<T> {
   List<SomeNamedObject> getObjects();
   void doSomething(P1 p1, T p2);
}

public class SomeNamedObject {
    private String text;
}

public class Clazz {

    private SomeInterface someInterface;

    ...

    public void someMethod() {
       // Error Type mismatch: cannot convert from element type Object to TestClass.SomeNamedObject
       for (SomeNamedObject someNamedObject :  someInterface.getObjects()) {
             // This loop won't compile as the someInterface.getObjects returns just a List and not a List<SomeNamedObject>
       }

       // Warning Type safety: The expression of type List needs unchecked 
       // conversion to conform to List<TestClass.SomeNamedObject>
       List<SomeNamedObject> objects = someInterface.getObjects();
       for (SomeNamedObject someNamedObject :  objects) {
             // This loop compiles 
       }
    }
}

Upvotes: 9

Views: 860

Answers (2)

Stefan
Stefan

Reputation: 848

You should note that you get a compiler warning when you asign to objects before the second loop.

Type safety: The expression of type List needs unchecked conversion to conform to 
 List<TestClass.SomeNamedObject>

This would have told you that for some reason your getObjects() method is returning a non generified List. Which explains why the first loop does not compile.

Because you forgot to generify your reference:

private SomeInterface someInterface;

If you dont generify it everything will use the raw type, including the signature of the declared method. Means it returns a raw List object instead of a List<SomeNamedObject> Do something like

private SomeInterface<Object> someInterface;

And it should work.

Upvotes: 3

mikej
mikej

Reputation: 66263

Because your instance variable private SomeInterface someInterface doesn't specify its generic type parameter then all use of generics is disabled for someInterface. This means that someInterface.getObjects() has the raw return type List rather than List<SomeNamedObject>. This is the reason the first example does not compile.

In the second example List<SomeNamedObject> objects = someInterface.getObjects() is putting in an explicit type for the list. You will see a warning when you do this though because the type safety is not guaranteed. This is the same behaviour you would see if getObjects() was defined as just List getObjects() without the type parameter.

Upvotes: 18

Related Questions