简体   繁体   中英

Reflection - Getting New Instance of unknown classes with unknown number of constructor parameters

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);
}

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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM