How to create a class literal of a known type: Class<List<String>>

89,602

Solution 1

You can always cast to what you need, like this

return (Class<List<String>>) new ArrayList<String>().getClass();

or

return (Class<List<String>>) Collections.<String>emptyList().getClass();

But I assume that's not what you are after. Well it works, with a warning, but it isn't exactly "beautiful".

I just found this

Why is there no class literal for wildcard parameterized types?

Because a wildcard parameterized type has no exact runtime type representation.

So casting might be the only way to go.

Solution 2

You should never use the construct Class<List<String>>. It is nonsensical, and should produce a warning in Java (but doesn't). Class instances always represent raw types, so you can have Class<List>; that's it. If you want something to represent a reified generic type like List<String>, you need a "super type token" like Guice uses:

http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html

Solution 3

You can implement that method like this:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}

Solution 4

The existence of a Class<List<String>> is inherently dangerous. here's why:

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}

Solution 5

Found this link on springframework.org which gives some insight.

E.g.

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();
Share:
89,602
skaffman
Author by

skaffman

Updated on January 16, 2020

Comments

  • skaffman
    skaffman over 4 years

    Take the following:

    public Class<List<String>> getObjectType() {
        // what can I return here?
    }
    

    What class literal expression can I return from this method which will satisfy the generics and compile? List.class won't compile, and neither will List.<String>class.

    If you're wondering "why", I'm writing an implementation of Spring's FactoryBean<List<String>>, which requires me to implement Class<List<String>> getObjectType(). However, this is not a Spring question.

    edit: My plaintive cries have been heard by the powers that be at SpringSource, and so Spring 3.0.1 will have the return type of getObjectType() changed to Class<?>, which neatly avoids the problem.

  • JRL
    JRL over 14 years
    @Bozho: the springframework link has a different method signature java.lang.Class<? extends T> getObjectType(). I've updated my answer to reflect the signature of the OP's question.
  • skaffman
    skaffman over 14 years
    Where did you find that quote?
  • skaffman
    skaffman about 14 years
    I agree that it's not a good idea, but Java permits it, and if you're trying to implement an interface, you may have no choice in the matter, so we still need a way of doing it (semi-)elegantly.
  • user
    user over 9 years
    Your first example did not work for me (SE 1.6), only the second example did. Instantiating the ArrayList to a variable and returning myVar.getClass() works though. found : java.lang.Class<capture#972 of ? extends java.util.ArrayList> required: java.lang.Class<java.util.List<com.foo.Bar>>
  • Peter Kriens
    Peter Kriens over 8 years
    That is a strange example. Since generics are not reified in runtime runtime casting bypasses the generic type system in many cases. Generics are mostly a compile time construct that allows you to further constrain a type from a class type. It would be useful if you could keep the generic signature because, as long as you don't cast, would make a lot of code more readable AND typesafe.
  • Martin Forte
    Martin Forte over 7 years
    I like this way because you don't need create a new instances.
  • TXN
    TXN over 4 years
    The outer cast is unnecessary. You can write it like this instead: return (Class)List.class;, which I find easier to read.