我在做什么
我在代码中使用了大量的反射,其中一部分是动态地反射创建类实例。我能够从我正在解析的数据中获取所需的类型和参数。我将数据放入Object[]
中,作为参数传递给Class.newinstance。有些参数是null
,因为我正在制作数据交叉引用器。这意味着我将获取两个数据集,并使用一个通用的Object
对它们进行交叉引用(我现在尝试具体制作的是Salesrep
,但此代码是动态的,因此可以更改(。这意味着,在解析一个数据集时,创建该对象的一些参数应该是null
,因为它们来自另一个数据集中。
问题和我尝试过的
不幸的是,每当我设置null
参数时,我都会得到一个Illegal Argument Exception
,说明我的参数数量不对。我已经检查了文档中的错误,它说只有当包装失败或实际存在错误数量的参数时才会抛出错误。我试着在谷歌上搜索,堆栈溢出,甚至一些github转发,我发现的只是一些关于方法的问题
//add in non null args to objectArray
Object arg = null;
objectArray.add(arg)
//causes the exception here anyways.
Class.newinstance(objectArray)
我试过直接添加null而不包装它,但这也不起作用。请注意,这些构造函数不是空的或零参数,它们只有一个,我可以确认包括null的参数数量等于所需数量。当参数不为null时,我还可以确认我正在传递正确的类型。我99%确信任何类型的参数都可以为null,或者至少我需要的参数类型确实可以为null(主要是基元和数组或其他集合(。我读过一些地方,当传递null时,它需要正确包装,并且它可能会将null误认为空对象数组参数。老实说,我只是不知道什么能奏效。我创建了一个try-catch块,它打印我传入的参数的数量和类型。它似乎每次都匹配,但它仍然会进入catch块。这是导致错误的我的代码:
代码以及如何理解
请注意:firstLineArray
是我的数据中构造函数参数名称的String[]
。并不是所有的构造函数参数都在其中一个数据集中,所以这段代码采用了实际的参数,并用可用数据填充它们。其他设置为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
这是我的Stack Trace。首先是我在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
类中的一个片段。
问题似乎是您传递的是List
而不是数组:
object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut);
// Passing a List ^^^^^^^^^^^
你需要这样做:
object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut.toArray());
你在帖子中没有说argArrayOut
是List
,但它显然是一个,因为你在上面调用了add
方法