664

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.

John Woo
264k70 gold badges507 silver badges500 bronze badges
asked Sep 16, 2008 at 18:04
6
  • 3
    Just tested performance on Android device. 10000 operations and: 8-9 ms takes new SomeClass(), 9-11 ms takes Factory<SomeClass>.createInstance() and 64-71 ms takes shortest reflection: SomeClass z = SomeClass.class.newInstance(). And all tests were in single try-catch block. Reflection newInstance() throws 4 different exceptions, remember? So I decided to use factory pattern Commented May 15, 2014 at 19:38
  • See also: stackoverflow.com/a/5684761/59087 Commented Mar 4, 2015 at 2:22
  • 4
    With Java 8, you now can pass a constructor reference or a lambda which makes this problem pretty trivial to work around. See my answer below for details. Commented Mar 30, 2016 at 16:54
  • I think this is bad idea to write such code, the are more elegant and readable ways of solving the underneath problem. Commented Mar 21, 2017 at 11:53
  • 2
    @DavidCitron "for a little while" he said... It has been eleven years since then... Commented Aug 21, 2019 at 18:55

29 Answers 29

378

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.

Lii
12.2k9 gold badges69 silver badges92 bronze badges
answered Sep 16, 2008 at 18:10

14 Comments

Yeah, I saw that solution, but it only works if you already have a reference to a Class object of the type that you want to instantiate.
Yeah I know. It would be nice if you could do E.class but that simply gives you Object.class because of erasure :)
That's the correct approach for this problem. It's usually not what you wish, but it's what you get.
And how do you call the createContents() method?
This is no longer the only way to do this, there is a better way now that doesn't require passing in a Class<?> reference using Guava and TypeToken, see this answer for the code and links!
|
156

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));
answered Mar 30, 2016 at 16:51

6 Comments

Good one. It avoids reflection and having to treat exceptions.
So nice. Unfortunately for Android users, this requires API level 24 or higher.
...and it’s not different to this even older answer showing that the technical pattern behind it is even older than Java’s support for lambda expressions and method references while you can even use that older code with them once you upgraded your compiler...
Would it be possible to put just SomeContainer stringContainer = new SomeContainer(String::new);?
@AaronFranke: No, because then you'd be using a raw type.
|
147

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.

answered Sep 16, 2008 at 18:18

9 Comments

Yes, this is nice especially if the generic class is abstract, you can do this in the concrete subclasses :)
This method also works if class Foo isn't abstract. But why does it only work on anonymous subclasses of Foo? Suppose we make Foo concrete (we leave out abstract), why will new Foo<Bar>(); result in an error, while new Foo<Bar>(){}; doesn't? (Exception: "Class cannot be cast to ParameterizedType")
@TimKuipers The <E> in class Foo<E> is not bound to any particular type. You will see the exceptional behavior whenever E is not statically bound, as in: new Foo<Bar>(), new Foo<T>() {...}, or class Fizz <E> extends Foo<E>. The first case isn't statically bound, it is erased at compile time. The second case substitutes another type variable (T) in place of E but is still unbound. And in the last case it should be obvious that E is still unbound.
An example of statically binding the type parameter would be class Fizz extends Foo<Bar> -- in this case, users of Fizz get something that is a Foo<Bar> and cannot be anything but a Foo<Bar>. So in this case, the compiler is happy to encode that information into the class metadata for Fizz and make it available as a ParameterizedType to reflection code. When you create an anonymous inner class like new Foo<Bar>() {...} it is doing the same thing, except instead of Fizz the compiler generates an "anonymous" class name that you won't know until the outer class is compiled.
It should be noted that this won't work if the type arguments are also a ParameterizedType. For example, Foo<Bar<Baz>>. You'll be creating an instance of ParameterizedTypeImpl which can't be explicitly created. Therefore, it is a good idea to check if getActualTypeArguments()[0] is returning a ParameterizedType. If it is, then you want to get the raw type, and create an instance of that instead.
|
90

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();
 }
}
answered Sep 16, 2008 at 18:36

3 Comments

..and how Factory.create() looks like?
@OhadR Factory<> is an interface and so there's no body. The point is you need a layer of indirections to pass the buck to methods that do "know" the required code to construct an instance. It's much better to do this with normal code rather than metalinguistic Class or Constructor as reflection brings a whole world of hurt.
Now days you can create a factory instance with a method reference expression like this: SomeContainer<SomeElement> cont = new SomeContainer<>(SomeElement::new);
27
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());
 }
}
answered Sep 3, 2010 at 12:41

3 Comments

Good approach by this code may cause ClassCastException if You use in the generic a generic type. Then You retrive the actualType argument You should check that it is also ParamterizedType and if so return his RawType (or something better than this). Another issue with this is when we extend more then once this code also will throw the ClassCastExeption.
Caused by: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class
@DamianLeszczyński-Vash will also fail with, e.g. class GenericHome<T> extends Home<T>{}
25

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).
answered Jan 7, 2013 at 7:11

Comments

25

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.

Lukasz Stelmach
5,4014 gold badges27 silver badges29 bronze badges
answered Aug 8, 2014 at 2:03

3 Comments

This solution works for a limited set of cases, just like @noah's answer with reflection. I tried them all today... And I ended at passing an instance of the parameter class to the parameterized class (in order to be able to call .newInstance() ). Very big deficiency of "generics"... new Foo<Bar>(Bar.class); ... class Foo<T> { private final Class<T> mTFactory; Foo(Class<T> tClass) { mTFactory = tClass; ... } T instance = tFactory.newInstance(); }
this works in all cases, even static factory methods that take generic parameters
public class Q26289147 ? Why tho
20

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);
answered Sep 13, 2012 at 13:12

2 Comments

cls.newInstance() has been depreciated in favour of cls.getDeclaredConstructor().newInstance().
@antikbd thanks for the hint! I've updated the example accordingly.
15

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
}
answered Apr 16, 2015 at 16:20

2 Comments

Technically you're not passing a function, you're passing a function object (also known as a functor).
Or maybe to overcome catching Exception use Supplier<E> instead.
10

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();
 }
}
zemiak
4013 silver badges5 bronze badges
answered Feb 12, 2014 at 1:31

1 Comment

I like this approach as it is readable and does not bring any casting magic. The downside is you have to implement createContents in every derived class. Even if you don't need it. The other approach is to make createContents not abstract but with empty implementation (return null/throws) ... in this case you can only implement it when needed.
7

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();
}
answered Sep 16, 2008 at 18:14

2 Comments

Yeah, this works the same even without generics--with generics the instantiation of this container becomes a bit redundant (you have to specify what "E" is twice).
well, that's what happens when you use Java and generics... they aren't pretty, and there are severe limitations...
7

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();
 }
}
answered Sep 17, 2008 at 20:19

Comments

7

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);
ETO
7,3371 gold badge22 silver badges40 bronze badges
answered Feb 10, 2016 at 12:32

2 Comments

Could you please tell me why you're downvoting when you do so? I don't see why the official workaround is a bad solution. Thanks.
I guess you get down votes, because your answer is essentially the same as Justin Rudd's: stackoverflow.com/a/75254/103412
6

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.

Daniel Methner
6263 gold badges7 silver badges22 bronze badges
answered Jan 16, 2019 at 9:07

Comments

5

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.

hichris123
10.2k15 gold badges58 silver badges70 bronze badges
answered Dec 17, 2008 at 22:09

2 Comments

And how do you get the exact class name of the generic type at runtime?
You'd have to save it using an instance of that class. Doable, though hardly convenient. If your generic had a member of type E (or T or whatever), getting it's binary name is just foo.getClass().getName(). Where does THAT instance comes from? I'm currently passing one into a constructor in the project I'm now working on.
4

Use the TypeToken<T> class:

public class MyClass<T> {
 public T doSomething() {
 return (T) new TypeToken<T>(){}.getRawType().newInstance();
 }
}
Tobias Tengler
7,5144 gold badges26 silver badges35 bronze badges
answered Jul 20, 2019 at 14:03

1 Comment

If you use Guava instead of GSON, it's a little different: (T) new TypeToken<T>(getClass()){}.getRawType().newInstance();
3

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

answered Jan 3, 2013 at 20:13

Comments

3

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();
answered Nov 7, 2014 at 8:13

Comments

3

what you can do is -

  1. First declare the variable of that generic class

    2.Then make a constructor of it and instantiate that object

  2. 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);

answered Jul 19, 2019 at 12:11

1 Comment

return entity.newInstance(); triggers a warning: "The method newInstance() from the type Class<E> is deprecated since version 9"
1

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.

answered Dec 4, 2014 at 20:09

Comments

0

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.

answered Sep 16, 2008 at 18:06

2 Comments

How would you even do it using reflection? The only method I see is Class.getTypeParameters(), but that only returns the declared types, not the run-time types.
0

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++; 
 }
}
answered Sep 16, 2008 at 18:42

Comments

0
return (E)((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
answered Mar 22, 2011 at 9:59

2 Comments

This does not work in my example in the original question. The superclass for SomeContainer is simply Object. Therefore, this.getClass().getGenericSuperclass() returns a Class (class java.lang.Object), not a ParameterizedType. This was actually already pointed out by peer answer stackoverflow.com/questions/75175/… as well.
Totally wrong: Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
0

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 );
 }
}
Aubin
14.9k11 gold badges67 silver badges88 bronze badges
answered Apr 6, 2012 at 11:26

1 Comment

Totally wrong: Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
0

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.

answered Dec 28, 2018 at 7:53

Comments

0

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)
 }
answered May 3, 2021 at 5:23

Comments

0

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.

answered Jun 16, 2021 at 11:05

Comments

0

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();
 } 
} 
answered Dec 5, 2022 at 12:57

Comments

-1

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);
answered Feb 4, 2014 at 13:00

2 Comments

this is worse than just passing the class object
You don't need to explicitly reference the class loader at all.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.