反射构造器wrong number of arguments错误
2020-03-31 本文已影响0人
鸡龙
记一次在获取构造器时报出wrong number of arguments
错误,在通过反射来使用数组或可变参数构造器时,反射出来的构造方法里使用的参数是数组类型。这时不能直接使用类型数组去入参给newInstance。我们看一下newInstance的代码
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
看到方法是使用Object的可变参数数组,如果使用具体类型数组去构造这个对象,newInstance方法会将使用构造具体类型的具体数量的构造器去构造这个对象。
举例:这是类C的一个构造器,需要使用B数组。
public C(B... bs){
for(B b:bs){
System.out.println(b.getName());
}
System.out.println("构造C");
}
使用反射构造报出错误。
B[] bs = new B[] {new B("name1",18,"des1"),new B("name2",20,"des2")};
Constructor constructor = C.class.getDeclaredConstructor(B[].class);
C c1 = (C)constructor.newInstance(bs);
![](https://img.haomeiwen.com/i14899865/14aeb83cda0782a7.png)
分析:这里虽然获取了B[]为参数的构造器,但是传入参数却是(B.class,B.class),所以运行的时候,就报出了错误的参数数量。所以在newInstance时,应该用Object数组将B[]转为Object。
正确写法:
B[] bs = new B[] {new B("name1",18,"des1"),new B("name2",20,"des2")};
Object parameters[]=new Object[] {bs};
Constructor constructor = C.class.getDeclaredConstructor(B[].class);
C c = (C)constructor.newInstance(parameters);
![](https://img.haomeiwen.com/i14899865/6045529a1c92739f.png)
虽然构造成功了,但我们怎么就知道了传入参数却是(B.class,B.class),我们再来看看,我们分析的对不对。
再创建一个构造方法
public C(B b1,B b2){
System.out.println("非可变构造器");
}
在启动方法中添加使用这个构造方法的反射构造器
Constructor constructor1 =
C.class.getDeclaredConstructor(B.class,B.class);
C c1 = (C)constructor1.newInstance(bs);
![](https://img.haomeiwen.com/i14899865/6fb112bdd83107b7.png)
结果证明猜想是正确的。