反射构造器wrong number of arguments错误

记一次在获取构造器时报出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);
错误

分析:这里虽然获取了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);

结果

虽然构造成功了,但我们怎么就知道了传入参数却是(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);
构造成功

结果证明猜想是正确的。

推荐阅读更多精彩内容

  • 类加载机制 1 什么是反射 Java反射机制是在运行状态中对于任意一个类,都能知道这个类的所以属性和方法;对于任何...
    凯玲之恋阅读 12,317评论 3 26
  • 对象的创建与销毁 Item 1: 使用static工厂方法,而不是构造函数创建对象:仅仅是创建对象的方法,并非Fa...
    孙小磊阅读 1,132评论 0 2
  • 美好的一周开始啦! 起床后,打开窗帘,哇哦!下雪了!可是虽然景色美,上班的路上又是难事,路滑我不敢开车。宝爸说还是...
    薇薇冰朵阅读 40评论 0 0
  • 说起云南,是很多亲们心中的旅游胜地,也经常有亲问采采卷耳去云南怎么玩? 这个问题说起来复杂啊亲们,因为云南真的很大...
    采采卷耳踏遍繁花似锦阅读 520评论 1 9
  • 发表于2013年11月7日 故乡的你词曲:邝鉴萍 多少个不眠不休的夜里,多少个风轻云淡的日子,每当我看到月亮就想...
    邝鉴萍阅读 72评论 1 5