通过Java发射机制调用可变参数函数

1、获取可变参数的函数

获取可变参数的函数与获取参数类型为数组类型一样。 clazz.getMethod("test", Object[].class);

其中Object为可变参数或者数组的数据类型

例如:

public void test(String ... params){

...

}

则获取该可变参数的函数如下:

Class clazz = Class.forName("com.demo003.MainThread");

Method method = clazz.getMethod("test", String[].class);

2、执行调用带有可变参数的函数

此时,我们应该如何将多个参数值传给可变参数呢?

method.invoke(obj , new String[]{"a" ,"b" ,"C"}) ,

或者是

method.invoke(mainThread, "a" ,"b" ,"c" );

这样调用对吗?

以上两种方式的调用会报:Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments

是不是感觉挺奇怪的?

其实Method的invoke方法的参数也是一个可变参数,如下是invoke的定义

那么当参数new String[]{"a" ,"b" ,"C"})传给invoke方法时,会自动拆分成3个参数:"a" ,"b" ,"c" ,那么invoke方法自然认为目标调用函数是带有3个形参的,

所以invoke方法调用目标函数时,会将这3个参数传递给目标函数,而目标函数仅仅是一个可变参数而已,所以就发生参数个数不一致的问题。对于反射来说,

是通过将数组类型对象传递给目标函数的可变参数的,即它只需要将多个参数组成一个数组,然后将这个数组传递给可变参数,然后目标函数的可变参数再自动将这个数组值自动拆分成多个参数值。

那么我们应该如何传呢?

既然知道了如果数组类型与invoke函数的参数类型(为Object)可以转换,并且为一维数组时,它会自动拆分成多个参数,导致最终参数个数不一致而出现异常。

同时知道了反射是通过将数组对象传递给目标函数的可变参数的。那么也就以意味这个,可以将这个需要传递数组类型对象转换invoke方法不可转换拆分的对象即可。

解决方案如下:

1)将数据类型对象强制转换成一个Object类型对象,这样就不会进行自动拆分了

method.invoke((Object) new String[]{"a" ,"b" ,"C"})

2)将当前数组再包装成一个一维数组,从而达到拆分出来的是一个数组对象

Object[]p = new Object[]{ new String[]{"a" ,"b" ,"C"} }

method.invoke(p)

可能还有其他的解决方案,只要最终达到invoke不能拆分该数组参数,或者是拆分后也只有该数组对象这个参数即可

时间: 2024-10-28 22:04:35

通过Java发射机制调用可变参数函数的相关文章

可变参数函数详解

可变参数函数又称参数个数可变函数(本文也简称变参函数),即函数参数数目可变.原型声明格式为: type VarArgFunc(type FixedArg1, type FixedArg2, -); 其中,参数可分为两部分:数目确定的固定参数和数目可变的可选参数.函数至少需要一个固定参数,其声明与普通函数参数相同:可选参数由于数目不定(0个或以上),声明时用"-"表示("-"用作参数占位符).固定参数和可选参数共同构成可变参数函数的参数列表. 由于参数数目不定,使用可

java中形参的可变参数的定义(如String... args) .

如果有下面的一个笔试题: 已知我们有如下的调用关系 logIt("log message 1 "); logIt("log message2","log message3"); logIt("log message4","log message5","log message6"); 请问下面的答案中哪个是正确的 A. public void logIt(String * msgs) B.

C语言中的可变参数函数 三个点“…”printf( const char* format, ...)

第一篇 C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的(用三个点“…”做参数占位符),实际调用时可以有以下的形式: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s",

C语言可变参数函数实现原理

一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本文地址:http://www.cnblogs.com/archimedes/p/variable-parameter.html,转载请注明源地址. 例如,对于函数: void fun(int a, int b, int c) { int d; ... } 其栈结构为 0x1ffc-->d 0x200

【C语言天天练(四)】可变参数函数

可变参数函数指可以接受可变数量参数的函数.比如printf函数就是一个可变参数函数. 要完成可变参数函数的编写,需要用到定义于stdarg.h头文件中的一个类型va_list和三个宏va_start.va_arg.va_end. 注意: 1.可变参数必须从头到尾按照顺序逐个访问.如果在访问几个可变参数后想半途中止,这是可以的.但是,如果想一开始就访问列表中的参数,那是不行的. 2.由于参数列表中的可变参数部分并没有原型,所以,所有作为可变参数传递给函数的值都将执行缺省参数类型提升. 3.参数列表

【转】C/C++中可变参数函数的实现

转自:http://www.cnblogs.com/cylee025/archive/2011/05/23/2054792.html 在C语言的stdarg.h头文件中提供了三个函数va_start, va_end,va_arg和一个类型va_list.利用它们,我们可以很容易实现一个可变参数的函数.首先简单介绍一下这三个函数. 假设现在有一个名为f的函数,其函数定义为: void f(int a, int b, ...) 那么,在函数的内部,为了获得这些可变参数,就需要利用到va_start.

ios开发-Object-C可变参数函数

简介 一个可变参数函数是指一个函数拥有不定的参数,即为一个函数可接收多个参数.有时我们会遇到一些算术问题需要用到,比如是计算传入参数的总和,字符串的连接或是其它操作过程,我们在 OC 里也经常使用,最经典的就是 NSLog( C 为 printf ) ,它可以指定格式的输出,格式化输出的内容. 现在我们先来看看普通函数的定义方法. 普通函数 一般我们定义的函数都是指定有多少个参数,如果是有三个参数,我们可以这样写. - (void)exampleObj:(NSString *)obj obj2:

C++ 11 可变参数模板和 boost::any 实现可变参数函数

1 class SqlHelper 2 { 3 public: 4 template <typename... Params> 5 static bool preparedExecute(sql::PreparedStatement* pstmt, Params... parameters) 6 { 7 return doPreparedExecute(pstmt, 1, parameters...); 8 } 9 10 private: 11 template <typename...

C语言可变参数函数详解示例

先看代码 printf("hello,world!");其参数个数为1个. printf("a=%d,b=%s,c=%c",a,b,c);其参数个数为4个. 如何编写可变参数函数呢?我们首先来看看printf函数原型是如何定义的.在linux下,输入man 3 printf,可以看到prinf函数原型如下: SYNOPSIS #include <stdio.h> int printf(const char *format, ...); 后面的三个点...