Is it possible to create an instance of a generic type in Java? I'm thinking based on what I've seen that the answer is no
(due to type erasure), but I'd be interested if anyone can see something I'm missing:
class SomeContainer<E>
{
E createContents()
{
return what???
}
}
EDIT: It turns out that Super Type Tokens could be used to resolve my issue, but it requires a lot of reflection-based code, as some of the answers below have indicated.
I'll leave this open for a little while to see if anyone comes up with anything dramatically different than Ian Robertson's Artima Article.
In Java 8 you can use the
Supplier
functional interface to achieve this pretty easily:You would construct this class like this:
The syntax
String::new
on that line is a constructor reference.If your constructor takes arguments you can use a lambda expression instead:
As you said, you can't really do it because of type erasure. You can sort of do it using reflection, but it requires a lot of code and lot of error handling.
If you mean
new E()
then it is impossible. And I would add that it is not always correct - how do you know if E has public no-args constructor? But you can always delegate creation to some other class that knows how to create an instance - it can beClass<E>
or your custom code like thisHere is an improved solution, based on
ParameterizedType.getActualTypeArguments
, already mentioned by @noah, @Lars Bohl, and some others.First small improvement in the implementation. Factory should not return instance, but a type. As soon as you return instance using
Class.newInstance()
you reduce a scope of usage. Because only no-arguments constructors can be invoke like this. A better way is to return a type, and allow a client to choose, which constructor he wants to invoke:Here is a usage examples. @Lars Bohl has shown only a signe way to get reified geneneric via extension. @noah only via creating an instance with
{}
. Here are tests to demonstrate both cases:Note: you can force the clients of
TypeReference
always use{}
when instance is created by making this class abstract:public abstract class TypeReference<T>
. I've not done it, only to show erased test case.You can with a classloader and the class name, eventually some parameters.