62

is there a way in java to get an instance of something like Class<List<Object>> ?

7 Answers7

78

how about

(Class<List<Object>>)(Class<?>)List.class
newacct
  • 119,665
  • 29
  • 163
  • 224
  • I like that idea. It causes unchecked cast warning, but it can be easily ignored I guess. Thanks for sharing! – Tomasz Błachowicz Mar 16 '11 at 23:30
  • This is brilliant. Exaclty what I needed to solve a difficult generics problem today. – kevinarpe Feb 13 '14 at 02:26
  • Is `(Class>)` really needed ? In my tests it seems like `(Class>)List.class` is enough. – alarive Jan 20 '15 at 10:16
  • @alarive: `List.class` has type `Class`. A cast from `Class` to `Class>` was illegal (because no type could possibly be a subtype of both) the last time I checked – newacct Jan 20 '15 at 10:20
  • This didn't work in my case ("The type List is not generic"), but `(Class>) (Class>) List.class` did. – Monkey Supersonic Nov 22 '17 at 14:11
  • 1
    @MonkeySupersonic: If you get "The type List is not generic", you have the wrong "List" type (probably the class `java.awt.List` instead of the interface `java.util.List`). Check your imports. – newacct Nov 24 '17 at 23:19
  • 1
    This question was asked in 2009 and I still see no proper solution even today in 2022... shame on Java! – TriCore Jan 29 '22 at 06:16
36
public final class ClassUtil {
    @SuppressWarnings("unchecked")
    public static <T> Class<T> castClass(Class<?> aClass) {
        return (Class<T>)aClass;
    }
}

Now you call:

Class<List<Object>> clazz = ClassUtil.<List<Object>>castClass(List.class);
Armhart
  • 361
  • 3
  • 2
  • 3
    Not a bad idea. This is basically the same as doing `(Class>)(Class>)List.class` but if you need several class objects, you will only have one unchecked cast inside the ClassUtil. – Dario Seidl Sep 17 '11 at 15:58
  • I like it, because you do not create new objects. Cool. Thanks. – Gábor Lipták Oct 19 '12 at 07:43
  • 1
    To provide some type safety, you could require the parameter to be `super` of T. `public static Class castClass(Class super T> aClass)` – Invitor Jan 04 '22 at 21:17
10

Because of type erasure, at the Class level, all List interfaces are the same. They are only different at compile time. So you can have Class<List> as a type, where List.class is of that type, but you can't get more specific than that because they aren't seperate classes, just type declarations that are erased by the compiler into explicit casts.

configurator
  • 40,828
  • 14
  • 81
  • 115
Yishai
  • 90,445
  • 31
  • 189
  • 263
6

As mentioned in other answers, Class represents an erased type. To represent something like ArrayList<Object>, you want a Type. An easy way of getting that is:

new ArrayList<Object>() {}.getClass().getGenericSuperclass()

The generic type APIs introduced in 1.5 are relatively easy to find your way around.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
2

You could use Jackson's ObjectMapper

ObjectMapper objectMapper = new ObjectMapper();
CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, ElementClass.class)

No unchecked warnings, no empty List instances floating around.

Lorcan O'Neill
  • 3,303
  • 1
  • 25
  • 24
0

You can get a class object for the List type using:

Class.forName("java.util.List")

or

List.class

But because java generics are implemented using erasures you cannot get a specialised object for each specific class.

jwoolard
  • 6,024
  • 9
  • 37
  • 37
0
List.class

the specific type of generics is "erased" at compile time.

Jason S
  • 184,598
  • 164
  • 608
  • 970