【问题标题】:How can I expand arguments in Java?如何在 Java 中扩展参数?
【发布时间】:2012-03-07 17:57:21
【问题描述】:

以下 Python sn-p 完全符合我的意思:

def function(a, b, c):
    print("%i :: %s :: %f" % (a,b,c))

a = 1
b = "abc"
c = 1.0

function(a, b, c)

list = [a, b, c]

# This is what I am searching for in Java
function(*(list))

所以我有一个类似列表的结构,我不知道它有多少个参数,但我知道它有正确数量的参数以及正确的类型和格式。我想将它们传递给一个方法。所以我必须“扩展”这些论点。有人知道如何在 Java 中这样做吗?

【问题讨论】:

  • 你在看forvarargs吗?
  • 定义“扩展”?从您的示例中不清楚这意味着什么。
  • 如果您只想使用 % 运算符之类的东西,可以使用 Formatter 类,如下面的回答所示。

标签: java python parameter-passing


【解决方案1】:

Java 没有这种功能,因为作为一种静态的强类型语言,一个方法采用统一类型的值的集合并不常见,这些值可以全部存储在某个复合对象(数组、列表等)中。 )。 Python 没有这个问题,因为一切都是动态类型的。您可以在 Java 中通过定义一个辅助方法来做到这一点,该方法采用单个对象来保存所有参数,然后在调用真实方法时将它们展开。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    您可以使用Object... 声明可选参数,这样您就可以传递任意数量的参数,然后将每个参数转换为所需的类型:

    public void method1(String p1, Integer p2) {
    }
    
    public void method2(Object... params) {
        method1((String)params[0], (Integer)params[1];
    }
    

    您可以拨打method2为:

    method2("abc", 1);
    

    当然,这个例子有点多余,因为你可以直接调用method1,但这不是我想要说明的。 :)

    【讨论】:

      【解决方案3】:

      你不能。在Java中,方法参数是在编译时检查的,由于数组的内容是在运行时才定义的,所以这种检查是不可能的。

      您最接近的解决方案是使用一个将数组作为参数的方法,并最终扩展参数以调用目标方法。

      【讨论】:

        【解决方案4】:

        你可以这样做:

        import java.util.Formatter;
        
        // ...
        
        StringBuilder target = new StringBuilder();
        Formatter formatter = new Formatter(target);
        
        List<Integer> integers = new ArrayList<Integer>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        
        formatter.format("%d %d %d", integers.toArray());
        System.out.println(target.toString());
        

        编辑: Javadoc for java.util.Formatter

        【讨论】:

          【解决方案5】:

          不建议这样做(正如 templatetypedef 的回答所说,对于强类型语言来说,这是一种非常不常见的模式),但您可以使用反射来做您想做的事情。

          SomeType foo = //obtained from elsewhere
          List<?> args = //obtained from somewhere else
          
          //this bit obtains the method handle
          Method theMethod = null;
          for (Method m : foo.getClass().getMethods()) {
              if (m.getName().equals("theMethodIWant") {
                  theMethod = m;
                  break;
              }
          }
          
          theMethod.invoke(foo, args.toArray()); //this is the line that does the magic
          

          一些相当严重的警告:

          • 与直接调用相比,反射可以产生显着的性能影响 - 比在像 python 这样的动态语言中更重要。这可能或可能不重要。如有疑问,请测量。

          • 如果没有找到同名的方法,获取方法句柄的块会产生一个空指针

          • 参数列表必须具有正确数量的参数和正确的类型。您有责任在其他地方验证这一点。这比在动态语言中更难,因为运行时会为您做更少(如果有的话)类型强制。

          • method.invoke() 可以引发本示例忽略的大量异常(IllegalAccessException、IllegalArgumentException、InvocationTargetException 等)。您必须适当地捕捉和处理这些错误

          • 如果被调用的方法不是公开的,那么调用它时您将不得不做更多的工作。

          • 此示例甚至没有尝试处理方法重载的情况。具有不同参数列表的两个名为“theMethodIWant”的方法将需要不同的方法来获取方法句柄。

          总而言之,如果可能,我建议不要使用反射。

          【讨论】:

            【解决方案6】:

            我认为这与您的初始代码具有相似的语法...

            public class MultiArgs {
            
                public static void main(String[] args) {
                    int a = 1;
                    String b = "abc";
                    double c = 1.0;
                    List<?> list = Arrays.asList(a, b, c);
            
                    System.out.println(function(a, b, c)); // 1 :: abc :: 1.000000
                    System.out.println(function(list.toArray())); // 1 :: abc :: 1.000000
                }
            
                private static <T extends Object> String function(T... objects) {
                    return String.format("%d :: %s :: %f", objects);
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-07-24
              • 1970-01-01
              • 2012-12-19
              • 1970-01-01
              • 1970-01-01
              • 2020-08-13
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多