Java传播运算符

时间:2017-09-24 09:34:56

标签: java

我不确定我在这里使用的词汇,如果我错了,请纠正我。

在Javascript中,我有以下代码:

let args = [1,2,3];

function doSomething (a, b, c) {
    return a + b + c;
}

doSomething(...args);

如您所见,在调用doSomething时,我可以使用...点差运算符将我的参数“转换”为1, 2, 3

现在,我正在尝试用Java做同样的事情。

假设我有一个Foo课程:

public class Foo {
    public int doSomething (int a, int b, int c) {
        return a + b + c;
    }
}

现在我想打电话给doSomething

int[] args = {1, 2, 3};

我想使用doSomething (...args)之类的内容,而不是调用doSomething(args[0], args[1], args[2])

我看到这在功能声明中是可行的,但我不想改变这种功能的实现。

7 个答案:

答案 0 :(得分:4)

在java中有变量参数的概念,使用它可以将不同数量的参数传递给同一个函数。

我将您的代码作为示例:

public class Foo {
    public int doSomething (int ...a) {
      int sum = 0;
      for (int i : a)
           sum += i;
        return sum;
    }
 }

现在您可以将此功能称为:

doSomething (args)

有关更多信息,请访问以下链接: http://www.geeksforgeeks.org/variable-arguments-varargs-in-java/

答案 1 :(得分:4)

实际上,由于兼容性原因,使用varargs function(Object... args)的方法的签名等效于用数组function(Object[] args)声明的方法。

因此,为了将任何集合传递给需要可变参数的函数,您需要将其转换为数组:

import java.util.Arrays;
import java.util.stream.Stream;

public class MyClass {

  static void printMany(String ...elements) {
     Arrays.stream(elements).forEach(System.out::println);
  }

  public static void main(String[] args) {
    printMany("one", "two", "three");
    printMany(new String[]{"one", "two", "three"});
    printMany(Stream.of("one", "two", "three").toArray(String[]::new));
    printMany(Arrays.asList("foo", "bar", "baz").toArray(new String[3]));
  }
}

所有这些printMany的呼叫将打印:

  

一个

     

两个

     

三个

它与传播算子并不完全相同,但是在大多数情况下,它已经足够好了。

答案 2 :(得分:3)

Java语言不提供操作员来执行此操作,但其类库可以提供您所需的功能。

  

[来自OP的评论] Foo的开发者可以自己选择doSomething函数的参数数量。然后我就可以构建一个" bag"参数并将其注入方法中。

使用反射API ,这就是它的用途。它要求您在数组中打包参数。还需要做很多额外的工作,包括包装/解包单个方法参数和方法结果,但是你可以在运行时检查签名,构造一个数组,然后调用方法。

class Test {
    public static int doSomething(int a, int b, int c) {
        return a + b + c;
    }
    // This variable holds method reference to doSomething
    private static Method doSomethingMethod;
    // We initialize this variable in a static initialization block
    static {
        try {
            doSomethingMethod = Test.class.getMethod("doSomething", Integer.TYPE, Integer.TYPE, Integer.TYPE);
        } catch (Exception e) {
        }
    }
    public static void main (String[] ignore) throws java.lang.Exception {
        // Note that args is Object[], not int[]
        Object[] args = new Object[] {1, 2, 3};
        // Result is also Object, not int
        Object res = doSomethingMethod.invoke(null, args);
        System.out.println(res);
    }
}

以上代码打印6(demo)。

答案 3 :(得分:2)

不幸的是,你不能这样做。 spread操作符在javascript中工作,因为允许函数接受任意类型的两个(左边的参数是undefined)或太多的参数(忽略额外的参数)。强大且静态类型的Java必须始终确切地知道在编译代码之前传递的参数的数量和类型。

你可能会发现Java 8的功能接口,方法引用和var-args的hackaround,但它需要这么多的样板,我甚至不会在这里发布它。

答案 4 :(得分:0)

如果你只需要通过这种方式调用几种方法,只需创建一个这样的包装类就可以不用Reflection:

主类(SpreadTest.java):

public class SpreadTest {
     public static void main(String []args){
        int[] a = {1, 2, 3};
        System.out.println(new FooWrapper().doSomething(a)); // 6
     } 
}

你的包装类(FooWrapper.java):

public class FooWrapper extends Foo {
    public int doSomething(int ...a) {
        return super.doSomething(a[0], a[1], a[2]);
    }
}

具有完成工作的方法的类(Foo.java):

public class Foo {
    public int doSomething(int a, int b, int c) {
        return a + b + c;
    }
}

答案 5 :(得分:0)

// A method that takes a variable number of integer arguments.
    static void fun(int ...a)
    {
        System.out.println("Number of arguments: " + a.length);
  
        // using for each loop to display contents of a
        for (int i: a)
            System.out.print(i + " ");
        System.out.println();
    }
  
    // Driver code
    public static void main(String args[])
    {
        // Calling the varargs method with different number
        // of parameters
        fun(100);         // one parameter
        fun(1, 2, 3, 4);  // four parameters
        fun();            // no parameter
    }

输出:

Number of arguments: 1
100 
Number of arguments: 4
1 2 3 4 
Number of arguments: 0

这是在 java 中提供可变数量参数的最简单示例。对于 JavaScript Guyz,这也称为 Rest Operator。但是,如果您了解 JS,请不要与此混淆。 要了解有关 Java 的更多信息,请参阅: [https://www.geeksforgeeks.org/variable-arguments-varargs-in-java/][1]

答案 6 :(得分:-3)

与众多评论相反,例如:通过@JoeC和@Henry以及不正确的答案,这个中是可能的。

  

我想使用像

这样的东西
doSomething (...args)
  

而不是调用doSomething(args [0],args [1],args [2])。

你需要:

public int doSomething (int ... args) {
    int sum = 0;
    for (int i : args)
    {
        sum += i;
    }
    return sum;
}
  

我不想改变这种功能的实现。

不可能,先验。要么正在添加三个参数,要么添加实际传递的参数。下定决心。