How to create an instance of an generic class in java?

68 Views Asked by At

I was wondering if it is possible to create a construtor function:


public <C, T> C newInstance(Class<C> constructor_class,
                              Class<T> type,
                              Object...parameters){
     // create a new Instance with the generic type and the paramters
     
     //so basicly like this, but with generics and parameters
     return constructor_class.newInstance();
}


1

There are 1 best solutions below

0
On

You basically can't. Your example is broken - what is type supposed to represent?

Let's say you want to dynamically create a HashMap<String, Integer>. This would require that you pass in HashMap.class, String.class, and Integer.class, but we run into a TON of problems right off the bat:

  • How do we know that HashMap has 2 args? We don't, so you'd have to pass 2 class references via varargs and at runtime I guess we throw an exception if you passed the wrong number of classes.
  • What if you pass Map, which cannot be instantiated at all?
  • But most of all, this is completely useless, generics that do not show up in method/field/class signatures are figments of the compiler's imagination: javac uses it during compilation to warn or error, as well as to generate invisible caste operations, and then chucks this info away. By doing it dynamically, all that 'at compile time' stuff cannot work by definition (we're compiling, not running, the whole point is for the types to be dynamic, so javac cannot do), so to javac it is useless, and the info is then chucked. So that makes it fully useless, then, no?

Furthermore, Class cannot be used to convey generics args. What if I wanted a HashMap<List<String>, Integer> instead? List<String> does not exist as a class literal, so java.lang.Class<T> cannot be used here. There are also class objects (specifically, int.class) that aren't legal in generics. So, we have ?, ? super Foo, A, B extends A, C extends A & Serializable, List<String> all as examples of things that can go in <> but which cannot be a java.lang.Class reference, and int.class that is a legal class ref but which cannot go in <>. You can't put a square peg in a round hole. Let alone the fact that even if you could, it would do literally absolutely nothing whatsoever (see point #3: This is useless - most generics, and definitely the generics you'd use here, affect compilation and cease to exist afterwards).

There are crazy hacks in this space (super type tokens, for example), but if you do not fully understand how generics work under the hood, there is 0.00001% or less chance you will be able to use such hacks usefully, so don't bother until then. And asking this question, especially with that pseudocode, strongly suggests you don't understand enough of it yet.