How to Instantiate a class in a generic class in java [duplicate] - java

I have got a template class as follows:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?

After type erasure, all that is known about T is that it is some subclass of Object. You need to specify some factory to create instances of T.
One approach could use a Supplier<T>:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T> object, and then use reflection.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}

Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>.
Using this pattern, you can get new instances of T, even if T has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.

This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}

If you're willing to subclass you can avoid erasure as well, check out
http://www.artima.com/weblogs/viewpost.jsp?thread=208860

You can get the class object of type T without passing any arguments.
Try this.
static class MyClass<T> {
Class<?> clazz;
#SafeVarargs
public MyClass(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException("Do not specify arguments");
clazz = dummy.getClass().componentType();
}
#Override
public String toString() {
return "MyClass<T = " + clazz.getName() + ">";
}
}
public static void main(String[] args) {
MyClass<String> s = new MyClass<>();
System.out.println(s);
Object i = new MyClass<Integer>();
System.out.println(i);
}
output:
MyClass<T = java.lang.String>
MyClass<T = java.lang.Integer>
You can instantiate an object of type parameter T like this.
clazz.getConstructor().newInstance();

One option would be to cast it with Object
{field = (T) new Object();}
field will initially be type Object, but then it will cast down to type T. This is an ugly one because reducing casting to zero is what the goal should be for object initializations. But I think this will work.

Class classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}

Related

Deep-copying a map [duplicate]

I have got a template class as follows:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?
After type erasure, all that is known about T is that it is some subclass of Object. You need to specify some factory to create instances of T.
One approach could use a Supplier<T>:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T> object, and then use reflection.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>.
Using this pattern, you can get new instances of T, even if T has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.
This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
If you're willing to subclass you can avoid erasure as well, check out
http://www.artima.com/weblogs/viewpost.jsp?thread=208860
You can get the class object of type T without passing any arguments.
Try this.
static class MyClass<T> {
Class<?> clazz;
#SafeVarargs
public MyClass(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException("Do not specify arguments");
clazz = dummy.getClass().componentType();
}
#Override
public String toString() {
return "MyClass<T = " + clazz.getName() + ">";
}
}
public static void main(String[] args) {
MyClass<String> s = new MyClass<>();
System.out.println(s);
Object i = new MyClass<Integer>();
System.out.println(i);
}
output:
MyClass<T = java.lang.String>
MyClass<T = java.lang.Integer>
You can instantiate an object of type parameter T like this.
clazz.getConstructor().newInstance();
One option would be to cast it with Object
{field = (T) new Object();}
field will initially be type Object, but then it will cast down to type T. This is an ugly one because reducing casting to zero is what the goal should be for object initializations. But I think this will work.
Class classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}

How do I make a method that creates a new instance of a generic class specified by an abstract class? [duplicate]

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.
You are correct. You can't do new E(). But you can change it to
private static class SomeContainer<E> {
E createContents(Class<E> clazz) {
return clazz.newInstance();
}
}
It's a pain. But it works. Wrapping it in the factory pattern makes it a little more tolerable.
In Java 8 you can use the Supplier functional interface to achieve this pretty easily:
class SomeContainer<E> {
private Supplier<E> supplier;
SomeContainer(Supplier<E> supplier) {
this.supplier = supplier;
}
E createContents() {
return supplier.get();
}
}
You would construct this class like this:
SomeContainer<String> stringContainer = new SomeContainer<>(String::new);
The syntax String::new on that line is a constructor reference.
If your constructor takes arguments you can use a lambda expression instead:
SomeContainer<BigInteger> bigIntegerContainer
= new SomeContainer<>(() -> new BigInteger(1));
I don't know if this helps, but when you subclass (including anonymously) a generic type, the type information is available via reflection. e.g.,
public abstract class Foo<E> {
public E instance;
public Foo() throws Exception {
instance = ((Class)((ParameterizedType)this.getClass().
getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
...
}
}
So, when you subclass Foo, you get an instance of Bar e.g.,
// notice that this in anonymous subclass of Foo
assert( new Foo<Bar>() {}.instance instanceof Bar );
But it's a lot of work, and only works for subclasses. Can be handy though.
You'll need some kind of abstract factory of one sort or another to pass the buck to:
interface Factory<E> {
E create();
}
class SomeContainer<E> {
private final Factory<E> factory;
SomeContainer(Factory<E> factory) {
this.factory = factory;
}
E createContents() {
return factory.create();
}
}
package org.foo.com;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Basically the same answer as noah's.
*/
public class Home<E>
{
#SuppressWarnings ("unchecked")
public Class<E> getTypeParameterClass()
{
Type type = getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) type;
return (Class<E>) paramType.getActualTypeArguments()[0];
}
private static class StringHome extends Home<String>
{
}
private static class StringBuilderHome extends Home<StringBuilder>
{
}
private static class StringBufferHome extends Home<StringBuffer>
{
}
/**
* This prints "String", "StringBuilder" and "StringBuffer"
*/
public static void main(String[] args) throws InstantiationException, IllegalAccessException
{
Object object0 = new StringHome().getTypeParameterClass().newInstance();
Object object1 = new StringBuilderHome().getTypeParameterClass().newInstance();
Object object2 = new StringBufferHome().getTypeParameterClass().newInstance();
System.out.println(object0.getClass().getSimpleName());
System.out.println(object1.getClass().getSimpleName());
System.out.println(object2.getClass().getSimpleName());
}
}
If you need a new instance of a type argument inside a generic class then make your constructors demand its class...
public final class Foo<T> {
private Class<T> typeArgumentClass;
public Foo(Class<T> typeArgumentClass) {
this.typeArgumentClass = typeArgumentClass;
}
public void doSomethingThatRequiresNewT() throws Exception {
T myNewT = typeArgumentClass.newInstance();
...
}
}
Usage:
Foo<Bar> barFoo = new Foo<Bar>(Bar.class);
Foo<Etc> etcFoo = new Foo<Etc>(Etc.class);
Pros:
Much simpler (and less problematic) than Robertson's Super Type Token (STT) approach.
Much more efficient than the STT approach (which will eat your cellphone for breakfast).
Cons:
Can't pass Class to a default constructor (which is why Foo is final). If you really do need a default constructor you can always add a setter method but then you must remember to give her a call later.
Robertson's objection... More Bars than a black sheep (although specifying the type argument class one more time won't exactly kill you). And contrary to Robertson's claims this does not violate the DRY principal anyway because the compiler will ensure type correctness.
Not entirely Foo<L>proof. For starters... newInstance() will throw a wobbler if the type argument class does not have a default constructor. This does apply to all known solutions though anyway.
Lacks the total encapsulation of the STT approach. Not a big deal though (considering the outrageous performance overhead of STT).
You can do this now and it doesn't require a bunch of reflection code.
import com.google.common.reflect.TypeToken;
public class Q26289147
{
public static void main(final String[] args) throws IllegalAccessException, InstantiationException
{
final StrawManParameterizedClass<String> smpc = new StrawManParameterizedClass<String>() {};
final String string = (String) smpc.type.getRawType().newInstance();
System.out.format("string = \"%s\"",string);
}
static abstract class StrawManParameterizedClass<T>
{
final TypeToken<T> type = new TypeToken<T>(getClass()) {};
}
}
Of course if you need to call the constructor that will require some reflection, but that is very well documented, this trick isn't!
Here is the JavaDoc for TypeToken.
From Java Tutorial - Restrictions on Generics:
Cannot Create Instances of Type Parameters
You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
As a workaround, you can create an object of a type parameter through reflection:
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.getDeclaredConstructor().newInstance(); // OK
list.add(elem);
}
You can invoke the append method as follows:
List<String> ls = new ArrayList<>();
append(ls, String.class);
Think about a more functional approach: instead of creating some E out of nothing (which is clearly a code smell), pass a function that knows how to create one, i.e.
E createContents(Callable<E> makeone) {
return makeone.call(); // most simple case clearly not that useful
}
When you are working with E at compile time you don't really care the actual generic type "E" (either you use reflection or work with base class of generic type) so let the subclass provide instance of E.
abstract class SomeContainer<E>
{
abstract protected E createContents();
public void doWork(){
E obj = createContents();
// Do the work with E
}
}
class BlackContainer extends SomeContainer<Black>{
protected Black createContents() {
return new Black();
}
}
Here is an option I came up with, it may help:
public static class Container<E> {
private Class<E> clazz;
public Container(Class<E> clazz) {
this.clazz = clazz;
}
public E createContents() throws Exception {
return clazz.newInstance();
}
}
EDIT: Alternatively you can use this constructor (but it requires an instance of E):
#SuppressWarnings("unchecked")
public Container(E instance) {
this.clazz = (Class<E>) instance.getClass();
}
If you want not to type class name twice during instantiation like in:
new SomeContainer<SomeType>(SomeType.class);
You can use factory method:
<E> SomeContainer<E> createContainer(Class<E> class);
Like in:
public class Container<E> {
public static <E> Container<E> create(Class<E> c) {
return new Container<E>(c);
}
Class<E> c;
public Container(Class<E> c) {
super();
this.c = c;
}
public E createInstance()
throws InstantiationException,
IllegalAccessException {
return c.newInstance();
}
}
Java unfortunatly does not allow what you want to do. See the official workaround :
You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
As a workaround, you can create an object of a type parameter through reflection:
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
You can invoke the append method as follows:
List<String> ls = new ArrayList<>();
append(ls, String.class);
You can use:
Class.forName(String).getConstructor(arguments types).newInstance(arguments)
But you need to supply the exact class name, including packages, eg. java.io.FileInputStream. I used this to create a math expressions parser.
Hope this's not too late to help!!!
Java is type-safe, meaning that only Objects are able to create instances.
In my case I cannot pass parameters to the createContents method. My solution is using extends unlike the answer below.
private static class SomeContainer<E extends Object> {
E e;
E createContents() throws Exception{
return (E) e.getClass().getDeclaredConstructor().newInstance();
}
}
This is my example case in which I can't pass parameters.
public class SomeContainer<E extends Object> {
E object;
void resetObject throws Exception{
object = (E) object.getClass().getDeclaredConstructor().newInstance();
}
}
Using reflection create run time error, if you extends your generic class with none object type. To extends your generic type to object convert this error to compile time error.
Use the TypeToken<T> class:
public class MyClass<T> {
public T doSomething() {
return (T) new TypeToken<T>(){}.getRawType().newInstance();
}
}
I thought I could do that, but quite disappointed: it doesn't work, but I think it still worths sharing.
Maybe someone can correct:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface SomeContainer<E> {
E createContents();
}
public class Main {
#SuppressWarnings("unchecked")
public static <E> SomeContainer<E> createSomeContainer() {
return (SomeContainer<E>) Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class[]{ SomeContainer.class }, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class<?> returnType = method.getReturnType();
return returnType.newInstance();
}
});
}
public static void main(String[] args) {
SomeContainer<String> container = createSomeContainer();
[*] System.out.println("String created: [" +container.createContents()+"]");
}
}
It produces:
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at Main.main(Main.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Line 26 is the one with the [*].
The only viable solution is the one by #JustinRudd
An imporovement of #Noah's answer.
Reason for Change
a] Is safer if more then 1 generic type is used in case you changed the order.
b] A class generic type signature changes from time to time so that you will not be surprised by unexplained exceptions in the runtime.
Robust Code
public abstract class Clazz<P extends Params, M extends Model> {
protected M model;
protected void createModel() {
Type[] typeArguments = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
for (Type type : typeArguments) {
if ((type instanceof Class) && (Model.class.isAssignableFrom((Class) type))) {
try {
model = ((Class<M>) type).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
Or use the one liner
One Line Code
model = ((Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]).newInstance();
what you can do is -
First declare the variable of that generic class
2.Then make a constructor of it and instantiate that object
Then use it wherever you want to use it
example-
1
private Class<E> entity;
2
public xyzservice(Class<E> entity) {
this.entity = entity;
}
public E getEntity(Class<E> entity) throws InstantiationException, IllegalAccessException {
return entity.newInstance();
}
3.
E e = getEntity(entity);
Here's an implementation of createContents that uses TypeTools (which I authored) to resolve the raw class represented by E:
E createContents() throws Exception {
return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
}
This approach only works if SomeContainer is subclassed so the actual value of E is captured in a type definition:
class SomeStringContainer extends SomeContainer<String>
Otherwise the value of E is erased at runtime and is not recoverable.
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 be Class<E> or your custom code like this
interface Factory<E>{
E create();
}
class IntegerFactory implements Factory<Integer>{
private static int i = 0;
Integer create() {
return i++;
}
}
return (E)((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
You can achieve this with the following snippet:
import java.lang.reflect.ParameterizedType;
public class SomeContainer<E> {
E createContents() throws InstantiationException, IllegalAccessException {
ParameterizedType genericSuperclass = (ParameterizedType)
getClass().getGenericSuperclass();
#SuppressWarnings("unchecked")
Class<E> clazz = (Class<E>)
genericSuperclass.getActualTypeArguments()[0];
return clazz.newInstance();
}
public static void main( String[] args ) throws Throwable {
SomeContainer< Long > scl = new SomeContainer<>();
Long l = scl.createContents();
System.out.println( l );
}
}
Here 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:
public class TypeReference<T> {
public Class<T> type(){
try {
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
if (pt.getActualTypeArguments() == null || pt.getActualTypeArguments().length == 0){
throw new IllegalStateException("Could not define type");
}
if (pt.getActualTypeArguments().length != 1){
throw new IllegalStateException("More than one type has been found");
}
Type type = pt.getActualTypeArguments()[0];
String typeAsString = type.getTypeName();
return (Class<T>) Class.forName(typeAsString);
} catch (Exception e){
throw new IllegalStateException("Could not identify type", e);
}
}
}
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:
import java.lang.reflect.Constructor;
public class TypeReferenceTest {
private static final String NAME = "Peter";
private static class Person{
final String name;
Person(String name) {
this.name = name;
}
}
#Test
public void erased() {
TypeReference<Person> p = new TypeReference<>();
Assert.assertNotNull(p);
try {
p.type();
Assert.fail();
} catch (Exception e){
Assert.assertEquals("Could not identify type", e.getMessage());
}
}
#Test
public void reified() throws Exception {
TypeReference<Person> p = new TypeReference<Person>(){};
Assert.assertNotNull(p);
Assert.assertEquals(Person.class.getName(), p.type().getName());
Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
Assert.assertNotNull(ctor);
Person person = (Person) ctor.newInstance(NAME);
Assert.assertEquals(NAME, person.name);
}
static class TypeReferencePerson extends TypeReference<Person>{}
#Test
public void reifiedExtenension() throws Exception {
TypeReference<Person> p = new TypeReferencePerson();
Assert.assertNotNull(p);
Assert.assertEquals(Person.class.getName(), p.type().getName());
Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
Assert.assertNotNull(ctor);
Person person = (Person) ctor.newInstance(NAME);
Assert.assertEquals(NAME, person.name);
}
}
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.
Note that a generic type in kotlin could come without a default constructor.
implementation("org.objenesis","objenesis", "3.2")
val fooType = Foo::class.java
var instance: T = try {
fooType.newInstance()
} catch (e: InstantiationException) {
// Use Objenesis because the fooType class has not a default constructor
val objenesis: Objenesis = ObjenesisStd()
objenesis.newInstance(fooType)
}
Withou default constructor
Objenesis
I was inspired with Ira's solution and slightly modified it.
abstract class SomeContainer<E>
{
protected E createContents() {
throw new NotImplementedException();
}
public void doWork(){
E obj = createContents();
// Do the work with E
}
}
class BlackContainer extends SomeContainer<Black>{
// this method is optional to implement in case you need it
protected Black createContents() {
return new Black();
}
}
In case you need E instance you can implement createContents method in your derived class (or leave it not implemented in case you don't need it.
As you mentioned, you can't get an instance from generics. IMO, you have to change the design and make use of FACTORY METHOD design pattern. In this manner you don't need your class or method to be generics:
class abstract SomeContainer{
Parent execute(){
return method1();
}
abstract Parent method1();
}
class Child1 extends Parent{
Parent method1(){
return new Parent();
}
}
class Child2 extends Parent{
Parent method1(){
return new Child2();
}
}
You can with a classloader and the class name, eventually some parameters.
final ClassLoader classLoader = ...
final Class<?> aClass = classLoader.loadClass("java.lang.Integer");
final Constructor<?> constructor = aClass.getConstructor(int.class);
final Object o = constructor.newInstance(123);
System.out.println("o = " + o);

Is it possible to initialise a generic class in a generic function [duplicate]

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.
You are correct. You can't do new E(). But you can change it to
private static class SomeContainer<E> {
E createContents(Class<E> clazz) {
return clazz.newInstance();
}
}
It's a pain. But it works. Wrapping it in the factory pattern makes it a little more tolerable.
In Java 8 you can use the Supplier functional interface to achieve this pretty easily:
class SomeContainer<E> {
private Supplier<E> supplier;
SomeContainer(Supplier<E> supplier) {
this.supplier = supplier;
}
E createContents() {
return supplier.get();
}
}
You would construct this class like this:
SomeContainer<String> stringContainer = new SomeContainer<>(String::new);
The syntax String::new on that line is a constructor reference.
If your constructor takes arguments you can use a lambda expression instead:
SomeContainer<BigInteger> bigIntegerContainer
= new SomeContainer<>(() -> new BigInteger(1));
I don't know if this helps, but when you subclass (including anonymously) a generic type, the type information is available via reflection. e.g.,
public abstract class Foo<E> {
public E instance;
public Foo() throws Exception {
instance = ((Class)((ParameterizedType)this.getClass().
getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
...
}
}
So, when you subclass Foo, you get an instance of Bar e.g.,
// notice that this in anonymous subclass of Foo
assert( new Foo<Bar>() {}.instance instanceof Bar );
But it's a lot of work, and only works for subclasses. Can be handy though.
You'll need some kind of abstract factory of one sort or another to pass the buck to:
interface Factory<E> {
E create();
}
class SomeContainer<E> {
private final Factory<E> factory;
SomeContainer(Factory<E> factory) {
this.factory = factory;
}
E createContents() {
return factory.create();
}
}
package org.foo.com;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Basically the same answer as noah's.
*/
public class Home<E>
{
#SuppressWarnings ("unchecked")
public Class<E> getTypeParameterClass()
{
Type type = getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) type;
return (Class<E>) paramType.getActualTypeArguments()[0];
}
private static class StringHome extends Home<String>
{
}
private static class StringBuilderHome extends Home<StringBuilder>
{
}
private static class StringBufferHome extends Home<StringBuffer>
{
}
/**
* This prints "String", "StringBuilder" and "StringBuffer"
*/
public static void main(String[] args) throws InstantiationException, IllegalAccessException
{
Object object0 = new StringHome().getTypeParameterClass().newInstance();
Object object1 = new StringBuilderHome().getTypeParameterClass().newInstance();
Object object2 = new StringBufferHome().getTypeParameterClass().newInstance();
System.out.println(object0.getClass().getSimpleName());
System.out.println(object1.getClass().getSimpleName());
System.out.println(object2.getClass().getSimpleName());
}
}
If you need a new instance of a type argument inside a generic class then make your constructors demand its class...
public final class Foo<T> {
private Class<T> typeArgumentClass;
public Foo(Class<T> typeArgumentClass) {
this.typeArgumentClass = typeArgumentClass;
}
public void doSomethingThatRequiresNewT() throws Exception {
T myNewT = typeArgumentClass.newInstance();
...
}
}
Usage:
Foo<Bar> barFoo = new Foo<Bar>(Bar.class);
Foo<Etc> etcFoo = new Foo<Etc>(Etc.class);
Pros:
Much simpler (and less problematic) than Robertson's Super Type Token (STT) approach.
Much more efficient than the STT approach (which will eat your cellphone for breakfast).
Cons:
Can't pass Class to a default constructor (which is why Foo is final). If you really do need a default constructor you can always add a setter method but then you must remember to give her a call later.
Robertson's objection... More Bars than a black sheep (although specifying the type argument class one more time won't exactly kill you). And contrary to Robertson's claims this does not violate the DRY principal anyway because the compiler will ensure type correctness.
Not entirely Foo<L>proof. For starters... newInstance() will throw a wobbler if the type argument class does not have a default constructor. This does apply to all known solutions though anyway.
Lacks the total encapsulation of the STT approach. Not a big deal though (considering the outrageous performance overhead of STT).
You can do this now and it doesn't require a bunch of reflection code.
import com.google.common.reflect.TypeToken;
public class Q26289147
{
public static void main(final String[] args) throws IllegalAccessException, InstantiationException
{
final StrawManParameterizedClass<String> smpc = new StrawManParameterizedClass<String>() {};
final String string = (String) smpc.type.getRawType().newInstance();
System.out.format("string = \"%s\"",string);
}
static abstract class StrawManParameterizedClass<T>
{
final TypeToken<T> type = new TypeToken<T>(getClass()) {};
}
}
Of course if you need to call the constructor that will require some reflection, but that is very well documented, this trick isn't!
Here is the JavaDoc for TypeToken.
From Java Tutorial - Restrictions on Generics:
Cannot Create Instances of Type Parameters
You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
As a workaround, you can create an object of a type parameter through reflection:
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.getDeclaredConstructor().newInstance(); // OK
list.add(elem);
}
You can invoke the append method as follows:
List<String> ls = new ArrayList<>();
append(ls, String.class);
Think about a more functional approach: instead of creating some E out of nothing (which is clearly a code smell), pass a function that knows how to create one, i.e.
E createContents(Callable<E> makeone) {
return makeone.call(); // most simple case clearly not that useful
}
When you are working with E at compile time you don't really care the actual generic type "E" (either you use reflection or work with base class of generic type) so let the subclass provide instance of E.
abstract class SomeContainer<E>
{
abstract protected E createContents();
public void doWork(){
E obj = createContents();
// Do the work with E
}
}
class BlackContainer extends SomeContainer<Black>{
protected Black createContents() {
return new Black();
}
}
Here is an option I came up with, it may help:
public static class Container<E> {
private Class<E> clazz;
public Container(Class<E> clazz) {
this.clazz = clazz;
}
public E createContents() throws Exception {
return clazz.newInstance();
}
}
EDIT: Alternatively you can use this constructor (but it requires an instance of E):
#SuppressWarnings("unchecked")
public Container(E instance) {
this.clazz = (Class<E>) instance.getClass();
}
If you want not to type class name twice during instantiation like in:
new SomeContainer<SomeType>(SomeType.class);
You can use factory method:
<E> SomeContainer<E> createContainer(Class<E> class);
Like in:
public class Container<E> {
public static <E> Container<E> create(Class<E> c) {
return new Container<E>(c);
}
Class<E> c;
public Container(Class<E> c) {
super();
this.c = c;
}
public E createInstance()
throws InstantiationException,
IllegalAccessException {
return c.newInstance();
}
}
Java unfortunatly does not allow what you want to do. See the official workaround :
You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
As a workaround, you can create an object of a type parameter through reflection:
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
You can invoke the append method as follows:
List<String> ls = new ArrayList<>();
append(ls, String.class);
You can use:
Class.forName(String).getConstructor(arguments types).newInstance(arguments)
But you need to supply the exact class name, including packages, eg. java.io.FileInputStream. I used this to create a math expressions parser.
Hope this's not too late to help!!!
Java is type-safe, meaning that only Objects are able to create instances.
In my case I cannot pass parameters to the createContents method. My solution is using extends unlike the answer below.
private static class SomeContainer<E extends Object> {
E e;
E createContents() throws Exception{
return (E) e.getClass().getDeclaredConstructor().newInstance();
}
}
This is my example case in which I can't pass parameters.
public class SomeContainer<E extends Object> {
E object;
void resetObject throws Exception{
object = (E) object.getClass().getDeclaredConstructor().newInstance();
}
}
Using reflection create run time error, if you extends your generic class with none object type. To extends your generic type to object convert this error to compile time error.
Use the TypeToken<T> class:
public class MyClass<T> {
public T doSomething() {
return (T) new TypeToken<T>(){}.getRawType().newInstance();
}
}
I thought I could do that, but quite disappointed: it doesn't work, but I think it still worths sharing.
Maybe someone can correct:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface SomeContainer<E> {
E createContents();
}
public class Main {
#SuppressWarnings("unchecked")
public static <E> SomeContainer<E> createSomeContainer() {
return (SomeContainer<E>) Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class[]{ SomeContainer.class }, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class<?> returnType = method.getReturnType();
return returnType.newInstance();
}
});
}
public static void main(String[] args) {
SomeContainer<String> container = createSomeContainer();
[*] System.out.println("String created: [" +container.createContents()+"]");
}
}
It produces:
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at Main.main(Main.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Line 26 is the one with the [*].
The only viable solution is the one by #JustinRudd
An imporovement of #Noah's answer.
Reason for Change
a] Is safer if more then 1 generic type is used in case you changed the order.
b] A class generic type signature changes from time to time so that you will not be surprised by unexplained exceptions in the runtime.
Robust Code
public abstract class Clazz<P extends Params, M extends Model> {
protected M model;
protected void createModel() {
Type[] typeArguments = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
for (Type type : typeArguments) {
if ((type instanceof Class) && (Model.class.isAssignableFrom((Class) type))) {
try {
model = ((Class<M>) type).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
Or use the one liner
One Line Code
model = ((Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]).newInstance();
what you can do is -
First declare the variable of that generic class
2.Then make a constructor of it and instantiate that object
Then use it wherever you want to use it
example-
1
private Class<E> entity;
2
public xyzservice(Class<E> entity) {
this.entity = entity;
}
public E getEntity(Class<E> entity) throws InstantiationException, IllegalAccessException {
return entity.newInstance();
}
3.
E e = getEntity(entity);
Here's an implementation of createContents that uses TypeTools (which I authored) to resolve the raw class represented by E:
E createContents() throws Exception {
return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
}
This approach only works if SomeContainer is subclassed so the actual value of E is captured in a type definition:
class SomeStringContainer extends SomeContainer<String>
Otherwise the value of E is erased at runtime and is not recoverable.
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 be Class<E> or your custom code like this
interface Factory<E>{
E create();
}
class IntegerFactory implements Factory<Integer>{
private static int i = 0;
Integer create() {
return i++;
}
}
return (E)((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
You can achieve this with the following snippet:
import java.lang.reflect.ParameterizedType;
public class SomeContainer<E> {
E createContents() throws InstantiationException, IllegalAccessException {
ParameterizedType genericSuperclass = (ParameterizedType)
getClass().getGenericSuperclass();
#SuppressWarnings("unchecked")
Class<E> clazz = (Class<E>)
genericSuperclass.getActualTypeArguments()[0];
return clazz.newInstance();
}
public static void main( String[] args ) throws Throwable {
SomeContainer< Long > scl = new SomeContainer<>();
Long l = scl.createContents();
System.out.println( l );
}
}
Here 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:
public class TypeReference<T> {
public Class<T> type(){
try {
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
if (pt.getActualTypeArguments() == null || pt.getActualTypeArguments().length == 0){
throw new IllegalStateException("Could not define type");
}
if (pt.getActualTypeArguments().length != 1){
throw new IllegalStateException("More than one type has been found");
}
Type type = pt.getActualTypeArguments()[0];
String typeAsString = type.getTypeName();
return (Class<T>) Class.forName(typeAsString);
} catch (Exception e){
throw new IllegalStateException("Could not identify type", e);
}
}
}
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:
import java.lang.reflect.Constructor;
public class TypeReferenceTest {
private static final String NAME = "Peter";
private static class Person{
final String name;
Person(String name) {
this.name = name;
}
}
#Test
public void erased() {
TypeReference<Person> p = new TypeReference<>();
Assert.assertNotNull(p);
try {
p.type();
Assert.fail();
} catch (Exception e){
Assert.assertEquals("Could not identify type", e.getMessage());
}
}
#Test
public void reified() throws Exception {
TypeReference<Person> p = new TypeReference<Person>(){};
Assert.assertNotNull(p);
Assert.assertEquals(Person.class.getName(), p.type().getName());
Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
Assert.assertNotNull(ctor);
Person person = (Person) ctor.newInstance(NAME);
Assert.assertEquals(NAME, person.name);
}
static class TypeReferencePerson extends TypeReference<Person>{}
#Test
public void reifiedExtenension() throws Exception {
TypeReference<Person> p = new TypeReferencePerson();
Assert.assertNotNull(p);
Assert.assertEquals(Person.class.getName(), p.type().getName());
Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
Assert.assertNotNull(ctor);
Person person = (Person) ctor.newInstance(NAME);
Assert.assertEquals(NAME, person.name);
}
}
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.
Note that a generic type in kotlin could come without a default constructor.
implementation("org.objenesis","objenesis", "3.2")
val fooType = Foo::class.java
var instance: T = try {
fooType.newInstance()
} catch (e: InstantiationException) {
// Use Objenesis because the fooType class has not a default constructor
val objenesis: Objenesis = ObjenesisStd()
objenesis.newInstance(fooType)
}
Withou default constructor
Objenesis
I was inspired with Ira's solution and slightly modified it.
abstract class SomeContainer<E>
{
protected E createContents() {
throw new NotImplementedException();
}
public void doWork(){
E obj = createContents();
// Do the work with E
}
}
class BlackContainer extends SomeContainer<Black>{
// this method is optional to implement in case you need it
protected Black createContents() {
return new Black();
}
}
In case you need E instance you can implement createContents method in your derived class (or leave it not implemented in case you don't need it.
As you mentioned, you can't get an instance from generics. IMO, you have to change the design and make use of FACTORY METHOD design pattern. In this manner you don't need your class or method to be generics:
class abstract SomeContainer{
Parent execute(){
return method1();
}
abstract Parent method1();
}
class Child1 extends Parent{
Parent method1(){
return new Parent();
}
}
class Child2 extends Parent{
Parent method1(){
return new Child2();
}
}
You can with a classloader and the class name, eventually some parameters.
final ClassLoader classLoader = ...
final Class<?> aClass = classLoader.loadClass("java.lang.Integer");
final Constructor<?> constructor = aClass.getConstructor(int.class);
final Object o = constructor.newInstance(123);
System.out.println("o = " + o);

How to get the class of type variable in Java Generics

I've seen similar questions but they didnt help very much.
For instance I've got this Generic Class:
public class ContainerTest<T>
{
public void doSomething()
{
//I want here to determinate the Class of the type argument (In this case String)
}
}
and Another Class which uses this Container Class
public class TestCase
{
private ContainerTest<String> containerTest;
public void someMethod()
{
containerTest.doSomething();
}
}
Is it possible to determinate the Class of the type argument in method doSomething() without having an explicit type variable/field or any constructor in ContainerTest Class?
Update: Changed format of ContainerTest Class
The only way is to store the class in an instance variable and require it as an argument of the constructor:
public class ContainerTest<T>
{
private Class<T> tClass;
public ContainerTest(Class<T> tClass) {
this.tCLass = tClass;
}
public void doSomething()
{
//access tClass here
}
}
If you are interested in the reflection way, I found a partial solution in this great article: http://www.artima.com/weblogs/viewpost.jsp?thread=208860
In short, you can use java.lang.Class.getGenericSuperclass() and java.lang.reflect.ParameterizedType.getActualTypeArguments() methods, but you have to subclass some parent super class.
Following snippet works for a class that directly extends the superclass AbstractUserType. See the referenced article for more general solution.
import java.lang.reflect.ParameterizedType;
public class AbstractUserType<T> {
public Class<T> returnedClass() {
ParameterizedType parameterizedType = (ParameterizedType) getClass()
.getGenericSuperclass();
#SuppressWarnings("unchecked")
Class<T> ret = (Class<T>) parameterizedType.getActualTypeArguments()[0];
return ret;
}
public static void main(String[] args) {
AbstractUserType<String> myVar = new AbstractUserType<String>() {};
System.err.println(myVar.returnedClass());
}
}
There is no "clean" way to get the Generic Type argument from within the class.
Instead, a common pattern is to pass the Class of the Generic Type to the constructor and keep it as an inner property juste as done in the java.util.EnumMap implementation.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/EnumMap.java
public class ContainerTest<T> {
Class<T> type;
T t;
public ContainerTest(Class<T> type) {
this.type = type;
}
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
public void doSomething() {
//There you can use "type" property.
}
}
No. It is not possible because of type erasure (the type parameters are compiled as Object + type casts). If you really need to know/enforce the type in runtime you may store a reference to a Class object.
public class ContainerTest<T> {
private final Class<T> klass;
private final List<T> list = new ArrayList<T>();
ContainerTest(Class<T> klass) {
this.klass = klass;
}
Class<T> getElementClass() {
return klass;
}
void add(T t) {
//klass.cast forces a runtime cast operation
list.add(klass.cast(t));
}
}
Use:
ContainerTest<String> c = new ContainerTest<>(String.class);
There is a way to get the runtime type of the type parameter by using Guava's TypeToken to capture it. The solution's disadvantage is that you have to create an anonymous subclass each time you need an instance of Container.
class Container<T> {
TypeToken<T> tokenOfContainedType = new TypeToken<T>(getClass()) {};
public Type getContainedType() {
return tokenOfContainedType.getType();
}
}
class TestCase {
// note that containerTest is not a simple instance of Container,
// an anonymous subclass is created
private Container<String> containerTest = new Container<String>() {};
#Test
public void test() {
Assert.assertEquals(String.class, containerTest.getContainedType());
}
}
The key of this solution is described in tha JavaDoc of TypeToken's constructor used in the code above:
Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.
If You can define like this
public class ContainerTest<T>
{
public void doSomething(T clazz)
{
}
}
Then it is possible

Instantiating object of type parameter

I have got a template class as follows:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
How do I create a new instance of T in my class?
After type erasure, all that is known about T is that it is some subclass of Object. You need to specify some factory to create instances of T.
One approach could use a Supplier<T>:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Usage might look like this:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatively, you can provide a Class<T> object, and then use reflection.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
Another non-reflective approach is to use a hybrid Builder / Abstract Factory pattern.
In Effective Java, Joshua Bloch goes over the Builder pattern in detail, and advocates a generic Builder interface:
public interface Builder<T> {
public T build();
}
Concrete builders can implement this interface, and outside classes can use the concrete builder to configure the Builder as required. The builder can be passed to MyClass as a Builder<T>.
Using this pattern, you can get new instances of T, even if T has constructor parameters or requires additional configuration. Of course, you'll need some way to pass the Builder into MyClass. If you can't pass anything into MyClass, then Builder and Abstract Factory are out.
This may be more heavyweight than what you're looking for, but it will also work. Note that if you take this approach, it would make more sense to inject the factory into MyClass when it is constructed instead of passing it into your method each time it is called.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
If you're willing to subclass you can avoid erasure as well, check out
http://www.artima.com/weblogs/viewpost.jsp?thread=208860
You can get the class object of type T without passing any arguments.
Try this.
static class MyClass<T> {
Class<?> clazz;
#SafeVarargs
public MyClass(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException("Do not specify arguments");
clazz = dummy.getClass().componentType();
}
#Override
public String toString() {
return "MyClass<T = " + clazz.getName() + ">";
}
}
public static void main(String[] args) {
MyClass<String> s = new MyClass<>();
System.out.println(s);
Object i = new MyClass<Integer>();
System.out.println(i);
}
output:
MyClass<T = java.lang.String>
MyClass<T = java.lang.Integer>
You can instantiate an object of type parameter T like this.
clazz.getConstructor().newInstance();
One option would be to cast it with Object
{field = (T) new Object();}
field will initially be type Object, but then it will cast down to type T. This is an ugly one because reducing casting to zero is what the goal should be for object initializations. But I think this will work.
Class classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}

Categories

Resources