The standard way in Java to work around type erasure is to pass a class token into the constructor. For example we could define a generic property class like this:
class Prop<T> {
public Prop(Class<T> type) {
this.type = type;
}
Class<T> type;
T t;
}
class IntProp extends Prop<Integer> {
public IntProp() {
super(Integer.class);
}
}
But what if I now want to use another generic type argument, such as a list and also keep its generics type. I would have liked to do this:
class ListProp<J> extends Prop<ArrayList<J>> {
Class<J> subtype;
public ListProp(Class<J> type) {
super(ArrayList<J>.class);
subtype = type;
}
}
class IntListProp extends ListProp<Integer> {
public IntListProp() {
super(Integer.class);
}
}
But of course super(ArrayList<J>.class)
does not compile, neither does super(ArrayList.class)
. What's the best way to solve this?
The generics kung fu you need to make your
ListProp
class compile is this line:Attempting to cast directly from
List.class
toClass<List<T>>
:results in a compile error:
But if you first cast to typed class
Class<?>
, albeit an unknown type, you can then cast it the desired typed class.The full compilable
ListProp
class is then.Something else you may consider, in case you need special code for creating/returning a list, is a typed getter for
t
onProp
:which you can then covariantly override in
ListProp
to return aList<T>
It should be noted that you only need the class token if your implementation uses the class, which is not shown in your example code. If you don't actually use the class token, you can let type inference do the typing for you.
Small Intro
I know one way you can workaround the problem. Type erasure works to erase types after when compiling since they are not needed to run. This is probably why you can't just access the class List with type. List in itself uses generics and so it would not make sense, or possible, to provide a class for that since in your case T is actually the type of the list elements. The class is actually ArrayList. What you are looking for is the type of collection you are using and the type of element you are using. I've changed your code a bit so that you can accept a constructor for both types.
Code