As we know Java uses erasure, so any Generic class cannot do
T t = new T();
So I was trying out Java reflection to have a class with Static methods, to instantiate any Class with any Constructor. Here is the code.
import java.lang.reflect.*;
public class GenericNewInstance {
public static <T> T createInstance(Class<T> cObj) {
try {
return cObj.newInstance();
} catch (InstantiationException e) {
System.out.println("Instantiation Exception");
return null;
} catch (IllegalAccessException e) {
System.out.println("Illegal Access Exception");
return null;
}
}
public static <T> T createInstanceUsingRelection(Class<T> c, Object... initArgs) {
Constructor<T> cTor = null;
Class<?>[] cObjs = new Class<?>[initArgs.length];
int i = 0;
for(Object o : initArgs) {
cObjs[i++] = o.getClass();
}
try {
cTor = c.getConstructor(cObjs);
} catch (SecurityException e) {
System.out.println("security exception. Cannot get Constructor");
return null;
} catch (NoSuchMethodException e) {
System.out.println("NoSuchMethodException Cannot get constructor");
return null;
}
try {
return cTor.newInstance(initArgs);
} catch (IllegalArgumentException e) {
System.out.println("Illegal Argument Exception");
return null;
} catch (InstantiationException e) {
System.out.println("Instantiation Exception");
return null;
} catch (IllegalAccessException e) {
System.out.println("Illegal Access Exception");
return null;
} catch (InvocationTargetException e) {
System.out.println("Invocation Target Exception");
return null;
}
}
}
Example for using this.
Integer i = GenericNewInstance.createInstanceUsingRelection(Integer.class, "0");
So my questions:
- Is this the right way to implement it? (or is it verbose?)
- What are the typical use cases of doing this?
- Can/Should we avoid using Reflection while using Generics?
Your code will fail at
c.getConstructor(cObjs)since this doesn’t take into account the type hierarchy. If any argument is a subtype of the constructor’s declared param type, this call will not return it. You’ll need quite a lot more type juggling to get it working. I advise you to take a look at the code that already solves this problem. Perhaps you can even use that library as-is, your choice. It’s the implementation code for Clojure, a JVM-based dynamic language that needs exactly this stuff. The library is available from the Maven central repo.BTW Your exception handling is redundant. Either just declare
throws Exceptionor catch anyExceptionand wrap it in aRuntimeException. When something fails, the original exception is the best diagnostic.