I have a class which takes a type token, and then generates objects of a type parameterized by that type (OK, it’s a bit more complicated than that, but this is a concise example):
public class Test {
public static void main(String[] args) throws Exception {
Holder<HashSet<Integer>> i = newObjectHolder(HashSet.class); // this fails
}
static class Holder<T> {
public Holder(T newInstance) {}
}
public static <T> Holder<T> newObjectHolder(Class<T> typeToken) throws Exception {
Constructor<T> ctor = typeToken.getConstructor();
return new Holder<T>(ctor.newInstance());
}
}
This works fine if passed non-generic types, like:
Holder<Integer> i = Test.newObjectHolder(Integer.class);
If the passed type token is generic, however, it doesn’t work, as in the indicated line above:
Holder<HashSet<Integer>> i = Test.newObjectHolder(HashSet.class); // this fails
I get the problem, but is there a solution? I’m OK to add @SuppressWarnings(“unused”) in the code for newObject, if it doesn’t reduce the safety. Intuitively, it seems that newObject should be able to to make a cast that works, we know that one “new” object of an erased generic type is the same as any other, and we haven’t otherwise used T in the method.
So, sheepishly, answering my own question…
I can’t find any way to do it with
Class<?>, but this magic technique called super type tokens seems to work well. Here’s the updated code:The
TypeReferencecode is given here, although I suspect that Guice’sTypeLiteralwould work just as well (but it doesn’t have newInstance code, you’d have to implement it).