Do you have any clue about how to write such method?
public abstract class AbstractClass{}
public class TrialClass extends AbstractClass{
public TrialClass(final String a, final String b){}
public TrialClass(final String a, final String b, final String c){}
}
public class getNewInstance(final Class<? extends AbstractClass> clazz, Object... constructorParameters){
//???
}
TrialClass trialClass = getNewInstance(TrialClass.class, "A", "B");
You can use Class. forName() to get a Class object of the desired class. Then use getConstructor() to find the desired Constructor object. Finally, call newInstance() on that object to get your new instance.
We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.
To pass an object as an argument we write the object name as the argument while calling the function the same way we do it for other variables. Syntax: function_name(object_name); Example: In this Example there is a class which has an integer variable 'a' and a function 'add' which takes an object as argument.
Using the new keyword in java is the most basic way to create an object. This is the most common way to create an object in java. Almost 99% of objects are created in this way. By using this method we can call any constructor we want to call (no argument or parameterized constructors).
Probably more flexible approach is to check all the constructors and find the compatible one like this:
public static <T> T getNewInstance(final Class<T> clazz, Object... constructorParameters) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Constructor<?> candidate = null;
for(Constructor<?> constructor : clazz.getConstructors()) {
if(Modifier.isPublic(constructor.getModifiers()) && isConstructorCompatible(constructor, constructorParameters)) {
if(candidate == null)
candidate = constructor;
else
throw new IllegalArgumentException("Several constructors found which are compatible with given arguments");
}
}
if(candidate == null)
throw new IllegalArgumentException("No constructor found which is compatible with given arguments");
return (T) candidate.newInstance(constructorParameters);
}
private static boolean isConstructorCompatible(Constructor<?> constructor, Object[] constructorParameters) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
if(parameterTypes.length != constructorParameters.length)
return false;
for(int i=0; i<parameterTypes.length; i++)
if(!isParameterCompatible(parameterTypes[i], constructorParameters[i]))
return false;
return true;
}
private static boolean isParameterCompatible(Class<?> type, Object parameter) {
if(parameter == null)
return !type.isPrimitive();
if(type.isInstance(parameter))
return true;
if(type.isPrimitive()) {
if (type == int.class && parameter instanceof Integer
|| type == char.class && parameter instanceof Character
|| type == byte.class && parameter instanceof Byte
|| type == short.class && parameter instanceof Short
|| type == long.class && parameter instanceof Long
|| type == float.class && parameter instanceof Float
|| type == double.class && parameter instanceof Double
|| type == boolean.class && parameter instanceof Boolean)
return true;
}
return false;
}
There are still open issues though like varargs-constructors. Also ambiguity cases will not be resolved like it's done by javac (for example, if you have MyObj(Object)
and MyObj(String)
constructor, you will not be able to use the latter one are both match).
The Class
method contains a getConstructor
method that takes an array of Class
as a parameter, corresponding to the constructor arguments. You have to build this array from your parameter array.
Something like that:
public <T> T getNewInstance(final Class<T> clazz, Object... constructorParameters) throws InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException{
Class[] parameterTypes = new Class[constructorParameters.length];
for(int i = 0; i < constructorParameters.length; i++) {
parameterTypes[i] = constructorParameters[i].getClass();
}
Constructor<T> constructor = clazz.getConstructor(parameterTypes);
return constructor.newInstance(constructorParameters);
}
Edit: as Codebender said, this doesn't work when a subtype is passed as the argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With