反射调用可变参数方法时,getMethod()需用String[].class而非String.class等;invoke()参数须按形参顺序一维展开,仅当实参数组需作为单个元素时才强制转Object。
![反射调用可变参数方法:invoke方法中object[]数组的传参技巧](https://img.php.cn/upload/article/001/242/473/177865340064478.jpeg?x-oss-process=image/resize,p_40)
反射调用可变参数方法时,invoke() 的第二个参数是 Object...(本质是 Object[]),但传参方式必须严格匹配目标方法的签名逻辑——尤其当目标方法本身接收可变参数(如 void test(String... args))时,容易因数组嵌套层级错误导致 IllegalArgumentException 或方法匹配失败。
可变参数方法在字节码中就是数组
Java 编译器把 void foo(String... args) 编译为 void foo(String[] args),二者方法签名完全相同。因此:
- 反射获取该方法时,需用
String[].class作为参数类型,例如:getMethod("foo", String[].class) - 不能写成
getMethod("foo", String.class, String.class),否则找不到方法 - 也不能用
null或空数组代替参数类型,必须显式传入String[].class
invoke() 传参:一维还是二维?关键看目标形参结构
假设目标方法是 public void log(String tag, Object... values),它有两个形参:第一个是普通 String,第二个是可变参数 Object...(即 Object[])。此时 invoke() 的参数数组必须是一维的,且按顺序排列:
- 正确写法:
method.invoke(obj, "DEBUG", "a", 123, true)
→ 自动打包为Object[] { "DEBUG", "a", 123, true },其中前1项对应tag,后3项被收进values数组 - 错误写法:
method.invoke(obj, new Object[]{"DEBUG", "a", 123, true})
→ 整个数组被当作第一个参数传入,tag接收到"DEBUG",values反而变成new Object[]{ "a", 123, true },逻辑错乱
特殊情况:目标方法只接受一个可变参数
比如 public void printAll(Object... items),它只有一个形参,类型是 Object[]。这时有两种合法调用方式:
- 展开传:直接列出所有实参
method.invoke(obj, "x", 42, new Date())
→ 运行时自动包装为Object[] { "x", 42, new Date() } - 显式传数组:把整个数组作为单个实参传入
Object[] data = { "x", 42, new Date() };<br>method.invoke(obj, (Object) data);
→ 注意强制转型为(Object) data,否则会被二次包装成Object[][]
避免常见陷阱的实用建议
反射调用可变参数方法出错,多数源于对“数组的数组”理解偏差。记住三点:
-
getMethod() 的参数类型列表,永远描述形参声明的类型,不是你打算传什么,而是方法定义里写了什么(
String...→String[].class) - invoke() 的参数列表,按形参顺序逐个填值,可变参数部分不额外包一层数组,除非你明确想把它当一个整体对象传
-
如果实参本身是数组,又想让它作为可变参数的全部元素,就直接展开;如果想让它作为可变参数里的一个元素(即数组本身是 items[0]),才需要
(Object) arr强转










