java反射调用main方法踩坑

时间:2021-06-24 17:56:28   收藏:0   阅读:0

被调用类

import java.util.Arrays;

public class TestMain {

  public static void main(String[] args) {
    System.out.println("TestMain");
  }

  public static void testA(String... names) {
    System.out.println("testA: " + Arrays.toString(names));
  }

  public void testB(String[] names) {
    System.out.println("testB: " + Arrays.toString(names));
  }

  public void testC(String... names) {
    System.out.println("testC: " + Arrays.toString(names));
  }

  public void testD(Object... objects) {
    System.out.println("testD: " + Arrays.toString(objects));
  }
}

调用类

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Client2 {

  public static void main(String[] args)
      throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Class<TestMain> aClass = TestMain.class;
    Method mainMethod = aClass.getDeclaredMethod("main", String[].class);
    //错误
    //mainMethod.invoke(null, new String[]{});
    //第一种方法
    mainMethod.invoke(null, (Object) new String[]{});
    //第二种方法
    mainMethod.invoke(null, new Object[]{new String[]{}});
    Method testAMethod = aClass.getDeclaredMethod("testA", String[].class);
    testAMethod.invoke(null, (Object) new String[]{"a"});
    Method testBMethod = aClass.getDeclaredMethod("testB", String[].class);
    testBMethod.invoke(new TestMain(), (Object) new String[]{"b"});
    Method testCMethod = aClass.getDeclaredMethod("testC", String[].class);
    testCMethod.invoke(new TestMain(), (Object) new String[]{"c"});
    //解析成多个参数
    new TestMain().testD(new String[]{"d", "e"});
    //解析成一个参数
    new TestMain().testD((Object) new String[]{"d", "e"});
  }

}

输出为

TestMain
TestMain
testA: [a]
testB: [b]
testC: [c]
testD: [d, e]
testD: [[Ljava.lang.String;@6c3708b3]

反射调用静态方法时,第一个参数为 null,当参数类型为数组或可变参数时,调用时必须将数组类型转换为Object

(Object) new String[]{}

或使用Object数组包装一层

new Object[]{new String[]{}}

不然会报错,参数类型不匹配

Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at com.imooc.sourcecode.java.javacompile.test5.Client2.main(Client2.java:17)

这是因为jdk1.4和1.5中的Method类设计有区别,1.4如下

public Object invoke(Object obj, Object[] args)

1.5如下

public Object invoke(Object obj, Object... args)

参数类型从数组变成了可变参数,如果直接传递new String[]{}参数,jdk1.4下会转换成多个参数,jdk1.5下是一个参数,jdk会向下兼容1.4,我们为了让编译器正确的解析参数,需要做上述两种转换,转换为 Object,或使用 Object数组包装一下。

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!