首页 > 解决方案 > 使用空参数调用 Class.newInstance 导致 IllegalArgumentException

问题描述

我在做什么

我在我的代码中使用了大量的反射,其中一部分是动态地反射地创建类实例。我能够从我正在解析的数据中获取所需的类型和参数。我将数据放入Object[]作为参数传递给 Class.newinstance。一些论点是null因为我正在制作数据交叉引用。这意味着我正在获取两个数据集并使用一个公共交叉引用它们Object(我现在正在尝试专门制作的一个是,Salesrep但此代码是动态的,因此可以更改)。这意味着在解析一个数据集时,创建这个对象的一些参数应该是null因为它们来自另一个数据集。

问题和我尝试过的

不幸的是,每当我设置null参数时,我都会收到一条Illegal Argument Exception说明我有错误数量的参数。我已经检查了该错误的文档,它说它仅在包装失败或实际上存在错误数量的参数时才抛出。我尝试在谷歌上搜索,堆栈溢出甚至一些 github 存储库,我发现的只是一些关于 method.invoke 的问题,建议执行以下操作:

//add in non null args to objectArray
Object arg = null;
objectArray.add(arg)
//causes the exception here anyways.
Class.newinstance(objectArray)

我试过直接添加 null 而不是包装它,但这也不起作用。请注意,这些构造函数不是空参数或零参数,只有其中一个,我可以确认包括空值在内的参数数量等于所需数量。当参数不为空时,我还可以确认我传递了正确的类型。我 99% 确信任何类型的参数都可以为空,或者至少我需要的参数类型确实可以为空(主要是原语和数组或其他集合)。我读过一些地方,当传递 null 时,它需要正确包装,并且它可能会将 null 误认为是空对象数组参数。老实说,我只是无法弄清楚什么会起作用。我创建了一个 try catch 块,打印我传入的参数数量,他们的类型和它似乎每次都匹配,但它仍然进入 catch 块。这是我的代码导致错误:

代码以及如何理解它

几个注意事项来理解这一点:firstLineArrayString[]我数据中的一个构造函数参数名称。并非所有构造函数参数都在其中一个数据集中,因此此代码采用这些参数并用可用数据填充它们。其他设置为null。这是使用两个映射完成的:argsWeHave将参数名称映射到数据并将argsWeNeed参数名称映射到其类型。这两个映射查看它们共有的参数名称,并将数据与其类型匹配,并argArrayOut按照构造函数需要的顺序将其传递给 。

for (int j = 0; j < numberOfArgsNeeded; j++) {
        //uses parameter name to match the argument string to its type in the constructor
        //if the parameter name in the constructor isn't found among the param names we have data for OR
        //if the parameter name in the header isn't found among the param names of the constructor, it adds a null element
        //basically if there is an argument the constructor needs, and we have that argument by name.
        if (argWeHave.containsKey(ParamNames[j]) && argWeNeed.containsKey(firstLineArray[i])){
            //DONE fix where argWeNeed.get(firstLineArray[i]) returns null. Handle it gracefully rather than having NPE.
            argArrayOut.add(stringToType(argArrayIn[i],argWeNeed.get(firstLineArray[i])));
            i++;
        }
        //if there is no match set this argument to null
        else{
            //TODO wrap the null value or make it properly accept null as an arg to the object[] for newinstance.
            Object arg = null;
            argArrayOut.add(arg);
        }
    }
    try {
        //form the new instance with the properly formed argArrayOut.
        object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut);
    } 
    //exception is thrown after the try. It always hits this catch block

这是我的堆栈跟踪。首先是我在 catch 块中打印到系统的内容:

Class type: Sales_Rep_Data.SalesRep
number of parameters in constructor: 5
number of arguments passed to constructor: 5
Types needed in constructor
class java.lang.String , class java.lang.String , class java.lang.String , 
class java.lang.String , class java.util.ArrayList
Types provided to constructor
class java.lang.String , class java.lang.String , class java.lang.String , 
null , null 

然后是实际的堆栈跟踪:

java.lang.IllegalArgumentException: wrong number of arguments
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at Sales_Rep_Data.ObjectFactory.getObjectImpl(ObjectFactory.java:79)
at Sales_Rep_Data.SalesRepbyId.Parse(SalesRepbyId.java:27)
at Sales_Rep_Data.Data_Parser.main(Data_Parser.java:45)

如您所见,根据我打印的内容,我有所需的数量和类型。我只是无法理解为什么会发生此错误。这一定是一些远程包装要求或者我很傻的东西。欢迎任何代码可读性建议。这段代码不能单独运行,它需要很多其他代码,这只是我ObjectFactory班级的一个片段。

标签: javadynamicreflectionconstructornull

解决方案


看起来问题在于您传递的是 aList而不是数组:

object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut);
//                                              Passing a List ^^^^^^^^^^^

你需要这样做:

object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut.toArray());

你没有在你的帖子中说那argArrayOut是 a List,但它显然是一个,因为你add在它上面调用了方法。


推荐阅读