views:

196

answers:

4

If you have a method with the signature:

Class<? extends List<String>> getObjectType()
{
        return ?????;
}

How do you return a proper generic version of the List class?

return List.class; //errors
return List<String>.class; //errors
return List.class<String>; //errors

what is the proper syntax to handle this?

+2  A: 

You need to explicitly cast it to the return type. This works:

return (Class<? extends List<String>>) List.class;

Yes it just looks wrong. This is just one of the many reasons Java's generics system is a mess.

John Meagher
Interesting, doing your suggestion gets me closer as eclipse stops complaining. but when I go to compile the class with the java compiler I get "inconvertible types found : java.lang.Class<java.util.List>required: java.lang.Class<? extends java.util.List<java.lang.String>>"
Odd, it works for me within eclipse, but not when compiled on the command line. I've never seen that before.
John Meagher
With the -nowarn option it works for the case of returning someList.getClass(), but I still get the same error you are seeing when trying it with List.class.
John Meagher
+1  A: 

You have to return the class of something that extends List<String>. ArrayList<String> is one example. You can try:

ArrayList<String> myList = new ArrayList<String>();
...
return (Class<? extends List<String>>)myList.getClass();
Bill the Lizard
The explicit cast is needed. The general getClass method returns type Class<?>.
John Meagher
@John: Thanks for pointing that out. I checked, and that is indeed the case. I updated my example to include the cast.
Bill the Lizard
+2  A: 

From the book "Effective Java" (Second Edition, page 137): "Do not use wildcard types as return types. Rather than providing additional flexibility for your users, it would force them to use wildcard types in their client code."

That said, to cast, you must first create a temporary variable:

@SuppressWarnings("unchecked")
Class<? extends List<String>> result = ....;
return result;

This works because you can have annotations on assignments. It doesn't work on return itself. You could also add that to the method but that would hide other problems as well.

Aaron Digulla
For me it didn't just warn, it actually produced a compile error until I added the cast.
Michael Myers
Correct. "List" and "List<...>" are completely different types (just like String and Integer), so you need the cast. But the cast will cause a warning and you need to suppress that.
Aaron Digulla
A: 

List.class and List<String>.class - in all this cases you need casting. Really you need a type, that has List<String> at runtime, somethig like this:

interface StringList extends List<String> {};

public Class<? extends List<String>> getObjectType() {
    return StringList.class;
}
serge_bg