Java 解压缩参数列表

2022-09-04 03:45:44

这是另一个问题,“我该如何在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列表,但是有没有办法(也许使用Reflectle库?)来解压缩这些参数以用于其他功能?...args


答案 1
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);
}

答案 2

如果您调用的函数不是 varargs 函数(用 ...声明),则确实需要使用反射。Method.invoke() 采用一个参数数组。Object[]

通过反射的困难部分是找到正确的方法(好吧,如果只有一个具有相同名称的方法,这很容易,否则非常困难)。

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


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

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