lkl22 / DeveloperDocuments

开发文档,日常工作中学习的技术知识整理,方便日后查阅.
Apache License 2.0
0 stars 0 forks source link

java通过反射调用main方法,报参数个数不匹配 #12

Closed lkl22 closed 3 years ago

lkl22 commented 3 years ago

image

运行报错:

java.lang.IllegalArgumentException: wrong number of arguments

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.lkl.androidstudy.MainTest.testMain(MainTest.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
lkl22 commented 3 years ago

原因(参考自 java反射main方法注意点):

java1.4是没有可变参数的,即Method.invoke(Obeject objecr ,Object obj[]{"xx","yy"});用数组传递多个参数 。 java1.5有了可变参数,即Method.invoke(Objet objecr,Object...args);用可变参数传递多个参数。

那是怎么导致的呢?

由于兼容性问题,在JDK1.4没有引入可变参数Object...类型,所以使用数组来表示,invoke函数接收到String数组后会进行拆分,得到两个String变量,但是没有main函数接受 两个String值,所以不行。

而且只要参数是new Object[]{“xxx”,”yyy”},javac 为了兼容1.4,只把它当作 jdk1.4 的语法进行理解,而不把它当作 jdk1.5 的语法解释,也就是说不能传递new String[]{};。

lkl22 commented 3 years ago

原因(参考自 java反射main方法注意点):

  1. java1.4是没有可变参数的,即Method.invoke(Obeject objecr ,Object obj[]{"xx","yy"});用数组传递多个参数 。
  2. java1.5有了可变参数,即Method.invoke(Objet objecr,Object...args);用可变参数传递多个参数。

那是怎么导致的呢?

由于兼容性问题,在JDK1.4没有引入可变参数Object...类型,所以使用数组来表示,invoke函数接收到String数组后会进行拆分,得到两个String变量,但是没有main函数接受 两个String值,所以不行。

而且只要参数是new Object[]{“xxx”,”yyy”},javac 为了兼容1.4,只把它当作 jdk1.4 的语法进行理解,而不把它当作 jdk1.5 的语法解释,也就是说不能传递new String[]{};。

那解决方法: 1、mainMethod.invoke(null, new Object[]{new String[]{"xxx"}});该方法还是会按1.4处理,会将参数打散,但没关系,里面就是对的参数new String[]{"xxx"}。 2、mainMethod.invoke(null,(Object)new String[]{"xxx"});不会打散,因为强转为Object了,编译器会认为这不是一个数组,此时是一个完整的参数。但注意他本质还是一个数组,作用仅仅是骗过编译器而已

特别注意:只有main方法是这样,其他普通方法不会。