2

I create a function like this

public <T extends ClientCoporate> void myFunction(List<T> clients){
    T client = new T(); // issue
    ....
}

IDE error Cannot instantiate the type T

Simple question, how can I create a new instance of whatever class extends ClientCoporate here? I try to search but no hope, if you can find any duplicate question feel free to put a flag for me. Thanks.

Dang Nguyen
  • 1,209
  • 1
  • 17
  • 29
  • `T` is Generics Type Variable you can't say `new` on any Generics Type Variable. If you want to use `client` then just write `T client;`. –  Jan 09 '19 at 09:39
  • 1
    Simple answer, you can't. – Henry Jan 09 '19 at 09:41
  • Runtime you need the class. You should either pass it to the function or make sure the specified list is not empty. In the latter case, you could try `clients.get(0).getClass().newInstance()` – Robert Kock Jan 09 '19 at 09:42

2 Answers2

9

You can't.

Because generics are erased in run-time and compiler does not know what type of object to create. T is simply a placeholder, so It is illegal to attempt to instantiate it.

Usually this problem is solved by

public <T extends ClientCoporate> void myFunction(Class<T> clazz, List<T> clients){
    T client = clazz.getDeclaredConstructor().newInstance();        ....
}
talex
  • 17,973
  • 3
  • 29
  • 66
7

One of the reasons you can't do this - though there are probably at least a couple more - is because the concrete type of T is not known at the point you are trying to construct it. We cannot say for sure that the concrete type of T has a no-argument constructor. The only thing we do know is that is has the methods in ClientCoporate.

Consider the following class:

class MyClientCoporate extends ClientCoporate // or implements, it doesn't matter
{
    private MyClientCoporate() {}
}

We couldn't use new T() on this class because the constructor is not public. That's one reason for the compiler to disallow it.

If you can change the signature of the method then I'd do something like this:

public <T extends ClientCoporate> void myFunction(List<T> clients, Supplier<T> constructor){
    T client = constructor.get();
    ...
}

Sample usage:

myFunction(aList, SomeClientCoporateClass::new);
Michael
  • 41,989
  • 11
  • 82
  • 128