java - 使用空参数调用 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 块。这是我的代码导致错误:
代码以及如何理解它
几个注意事项来理解这一点: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
这是我的堆栈跟踪。首先是我在 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
班级的一个片段。
解决方案
看起来问题在于您传递的是 aList
而不是数组:
object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut);
// Passing a List ^^^^^^^^^^^
你需要这样做:
object_to_add = (ObjectImplementation) constructor.newInstance(argArrayOut.toArray());
你没有在你的帖子中说那argArrayOut
是 a List
,但它显然是一个,因为你add
在它上面调用了方法。
推荐阅读
- amazon-s3 - 错误 - 在 pod 失败时将 s3fs 与 kubernetes 一起使用时出现“传输端点未连接”
- reactjs - 如何在 react-konva 中捕获视频的第一帧
- gcc - 在 centOS 上安装 PETSc 时检测到一些奇怪的错误
- python - 如何在张量中添加新维度
- java - Crinteria Join make AND insetad of OR
- python - 如何在plotly和python中使用make_subplot绘制多个图表
- azure-devops - 将所有带有历史记录、附件、链接的工作项从 TFS 看板迁移到 Azure 板
- java - 如何使用 Java 以编程方式将 powerpoint (pptx) 导出到带有动画的视频
- python-3.x - 运行pytest时无法从django连接到postgres数据库
- python - 从字符串中删除以分号分隔的重复子字符串