Reputation: 421
First of all, I am new to Reflection. I have been working on a large project and I needed to use reflection on some parts (Yes I definitely need it). So I thought, I should create a Reflection Helper class which will be able to create new instances of any class with any number of parameters within my project.
As an example to my question: Normally(as far as I know), to create an instance of a class which has 2 strings as parameters in its constructor;
Class.getConstructor(String.class, String.class).newInstance("Arg_1", "Args_2");
will do the job. However, in my case I need a method which will work for any class with any constructor. So I created these methods but it doesn't seem to work, I keep getting NoSuchMethodException
. I need help at making it work.
private static String packagePrefix = "com.***";
public static Class<?> getClass(String className) throws ClassNotFoundException {
return Class.forName(packagePrefix + "." + className);
}
public static Object getClassInstance(String className, Object... args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Class<?>[] cArgs = new Class[args.length];
for (int i = 0; i < args.length; i++) {
cArgs[i] = args[i].getClass();
}
return getClass(className).getConstructor(cArgs).newInstance(args);
}
Upvotes: 1
Views: 1818
Reputation: 5948
In your comment you are saying that you have class that takes 4 arguments
Skill(Monster m, Integer procChance, Integer duration, Integer severity)
but you are trying to reflectively create it using only 3 arguments:
Skill skill = (Skill) ReflectionHelper.getClassInstance(skillPackagePrefix + skillType.getName(), monster, procChance, params);
Even thought that param
is an array of 2 integers (as you commented) it will be treated by Java as array argument and wont be merged into Object... args
varargs. The above code will work only for the following constructor:
Skill(Monster m, Integer procChance, Integer[] params)
Upvotes: 0
Reputation: 43661
In general, you can't "create new instances of any class with any number of parameters". If there is not such constructor then you will not be able to call it.
Next, Class.getConstructor
find the constructor with given formal parameter types, not assignment-compatible types. So if you have Foo(Number)
you'll not find this constructor with Foo.class.getConstructor(Long.class)
. You'll have to iterate over Class.getConstructors
and search for the constructor which has parameter types assignment-compatible types of your parameters.
Luckily, this was done a thousand times already. See ConstructorUtils.invokeConstructor from Commons BeanUtils, for instance. The implementation is far from trivial.
Upvotes: 3