Java解包参数列表

时间:2011-05-19 17:39:09

标签: java reflection

这是另一个问题“我如何用Java做这个?”在Python中,我可以使用'*'符号解压缩参数,如下所示:

>>> range(3, 6)             # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args)            # call with arguments unpacked from a list
[3, 4, 5]

Java支持使用...args语法获取args列表,但是有没有办法(可能使用Reflection库?)解压缩其他函数的那些?

2 个答案:

答案 0 :(得分:7)

public void printStrings(String... strings)
{
   // the strings parameter is really a String[].
   // You could do anything to it that you normally
   // do with an array.
   for(String s : strings){
      System.out.println(s);
   }
}

可以像这样调用:

String[] stringArray = new String[10];
for(int i=0; i < stringArray.length; i++){
   stringArray[i] = "String number " + (i+1);
}

printStrings(stringArray);

...语法实际上是数组的语法糖。

Java没有您描述的功能,但您可以通过多种方式伪造它。

我认为最接近的近似意味着使用varargs重载你想要以这种方式使用的任何函数。

如果你有一些方法:

public void foo(int a, String b, Widget c) { ... }

你可以超载它:

public void foo(Object... args) {
    foo((Integer)args[0], (String)args[1], (Widget)args[2]);
}

但这非常笨拙,容易出错并难以维护。

更一般地说,你可以使用反射来使用任何参数调用任何方法,但它也有很多陷阱。这是一个错误的,不完整的例子,说明它如何变得如此丑陋:

public void call(Object targetInstance, String methodName, Object... args) {
    Class<?>[] pTypes = new Class<?>[args.length];
    for(int i=0; i < args.length; i++) {
        pTypes[i] = args[i].getClass();
    }
    Method targetMethod = targetInstance.getClass()
              .getMethod(methodName, pTypes);
    targetMethod.invoke(targetInstance, args);
}

答案 1 :(得分:1)

如果您调用的函数不是varargs函数(用...声明),那么您需要使用反射。 Method.invoke()获取数组Object[]个参数。

通过反思的困难部分是找到正确的方法(嗯,如果只有一种方法具有相同的名称,那就很容易了,否则很难)。

费用是查找/调用方法的额外时间。


当然,如果您在编译时知道具体方法,那么您可以手动处理,例如这里有一个3参数函数:

Object[] args = /* get args from somewhere */
callSomeNonVarargsFunction((Cast1)args[0], (Cast1)args[1], (Cast1)args[2]);
相关问题