Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java casting ".class"-operator used on a generic type, e.g. List, to "Class<List<?>>" and to "Class<List<Integer>>"

I use the .class-operator to supply information about the contained type to a generic class. For non-generic contained types, e.g. Integer.class, this works without any problems. But with the contained type being a generic, e.g. List<Integer>.class or List.class it results in compile time errors about class casting.

There is a way to circumvent the errors, but I'm curious about what is happening here. Can someone explain what is happening?, why things are as they are?, and what the best way to circumvent the problem is?

The following lines demonstrate the problem: Note the outer generic type expects Class<T> as parameter, so in this case Class<List<Integer>>.

Class<Integer> tInt = Integer.class;                     // Works as expected.
Class<List> tList = List.class;              // Works with warning, but is not
                                             // what i'm looking for.
Class<List<Integer>> tListInt1 = List.class;                          // Error
Class<List<Integer>> tListInt2 = (Class<List<Integer>>) List.class;   // Error
Class<List<?>> tListGeneric = (Class<List<Integer>>) List.class;      // Error

The next line works:

Class<List<Integer>> tListInt3 = 
                (Class<List<Integer>>) ((Class<Integer>)List.class);

Why do the declarations of tListInt2 and tListGeneric give and error? Why does upcast and then downcast with tListInt3 not produce an error? Is there a better way to declare tListInt3?

With kind regards,
Kasper van den Berg

ps. Let me know if you like to see code the outer generic container that needs this type information; i'll post it if needed.

like image 954
Kasper van den Berg Avatar asked Sep 21 '11 15:09

Kasper van den Berg


People also ask

What is generic type casting in Java?

The Java Generics programming is introduced in J2SE 5 to deal with type-safe objects. It makes the code stable by detecting the bugs at compile time. Before generics, we can store any type of objects in the collection, i.e., non-generic. Now generics force the java programmer to store a specific type of objects.

What is the generic class type called?

Generic Classes These classes are known as parameterized classes or parameterized types because they accept one or more parameters.

What is a parameterized or generic type?

A parameterized type is an instantiation of a generic type with actual type arguments. A generic type is a reference type that has one or more type parameters. These type parameters are later replaced by type arguments when the generic type is instantiated (or declared ).


1 Answers

Class<List<Integer>> tListInt3 = 
            (Class<List<Integer>>) ((Class<Integer>)List.class);

that doesn't work. you probably meant

Class<List<Integer>> tListInt3 = 
            (Class<List<Integer>>) ((Class)List.class);

we can always cast from one type to another by up-cast then down-cast

    Integer x = (Integer)(Object)"string";

The type of List.class is Class<List>; it is not a subtype/supertype of Class<List<Whatever>> therefore direct cast between the two types is illegal.

It can be argued that Class<List<Integer>> doesn't exist - there is only a class for List; there is no such class for List<Integer> (which really is just List at runtime)

However, this is a flaw of Java type system; in practice we do need things like Class<List<Integer>>. Our solution - casting and pretending Class<List<Int>> exits - is likewise flawed - but it's not our fault.

like image 143
irreputable Avatar answered Sep 28 '22 16:09

irreputable