Java 扩展运算符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46388620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 02:20:13  来源:igfitidea点击:

Java spread operator

java

提问by Hammerbot

I am not sure of the vocabulary I am using here, please correct me if I'm wrong.

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

In Javascript, I had the following code:

在 Javascript 中,我有以下代码:

let args = [1,2,3];

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

doSomething(...args);

As you can see, when calling doSomething, I am able to use the ...spread operator in order to "transform" my arguments into 1, 2, 3.

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

Now, I'm trying to do the same thing with Java.

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

Let's say I have a Fooclass:

假设我有一Foo堂课:

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

And now I want to call the doSomething:

现在我想调用doSomething

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

I'd like to use something like doSomething (...args)instead of calling doSomething(args[0], args[1], args[2]).

我想使用类似的东西doSomething (...args)而不是调用doSomething(args[0], args[1], args[2]).

I saw that this is possible in the declaration of functions, but I'd like not to change the implementation of such a function.

我在函数声明中看到这是可能的,但我不想改变这样一个函数的实现。

采纳答案by dasblinkenlight

Java language does not provide an operator to do this, but its class library has a facility to do what you need.

Java 语言不提供操作符来执行此操作,但它的类库具有执行您需要的功能的工具。

[from OP's comment] The developer of Foo could choose himself the number of arguments that function doSomething takes. I would then be able to construct a "bag" of arguments and inject it in the method.

[来自 OP 的评论] Foo 的开发人员可以自己选择函数 doSomething 所采用的参数数量。然后我就可以构造一个参数的“包”并将它注入到方法中。

Use reflection API, this is what it is for. It requires you to package arguments in an array. There is a lot of extra work required, including wrapping/unwrapping individual method arguments, and method result, but you can check the signature at run-time, construct an array, and call the method.

使用反射 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);
    }
}

The above code prints 6 (demo).

上面的代码打印 6 ( demo)。

回答by Nishesh Pratap

In java there is concept of Variable Arguments, using which you can pass different numbers of arguments to same function.

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

I am taking your code as an example :

我以您的代码为例:

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

Now you can call this function as :

现在你可以调用这个函数:

doSomething (args)

For more information you can visit below link : http://www.geeksforgeeks.org/variable-arguments-varargs-in-java/

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

回答by user207421

Contrary to numerous comments, e.g. by @JoeC and @Henry, and incorrect answers, this ispossible in Java.

与众多评论(例如@JoeC 和@Henry)以及错误答案相反,这在Java 中可能的。

I'd like to use something like

我想使用类似的东西

doSomething (...args)

instead of calling doSomething(args[0], args[1], args[2]).

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

You need:

你需要:

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

I'd like not to change the implementation of such a function.

我不想改变这样一个功能的实现。

Impossible, a priori. Either you are adding exactly three arguments, or as many arguments as were actually passed. Make up your mind about this.

不可能,先验的。要么添加正好三个参数,要么添加与实际传递的参数一样多的参数。对这件事下定决心。

回答by Leo Aso

Unfortunately, you can't do this. The spread operator works in javascript because functions are allowed to accept two few (left out arguments are undefined) or too many arguments (extra arguments are ignored) of any type. Java, being strongly and statically typed, must always know exactly how many and what kind of arguments you are passing before you even compile the code.

不幸的是,你不能这样做。展开运算符在 javascript 中有效,因为函数允许接受undefined任何类型的两个少数(遗漏的参数是)或过多的参数(忽略额外的参数)。Java 是强类型和静态类型的,在编译代码之前,必须始终确切地知道要传递的参数数量和类型。

You can probably find a hackaround with Java 8's functional interfaces, method references and var-args, but it would require so much boilerplate that I won't even bother posting it here.

您可能会找到有关 Java 8 的函数式接口、方法引用和 var-args 的 hackaround,但它需要大量样板文件,我什至懒得在这里发布。

回答by Mikhail Batcer

If you need to call only few methods this way, you can do without Reflection simply by creating a wrapper class like this:

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

Main class (SpreadTest.java):

主类(SpreadTest.java):

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

Your wrapper class (FooWrapper.java):

你的包装类(FooWrapper.java):

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

The class with the method which does the work (Foo.java):

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

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

回答by Krzysztof At?asik

Actually, because for compatibility reasons, the signature of a method, which is using varargs function(Object... args)is the equivalent of a method declared with an array function(Object[] args).

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

Therefore in order to pass and spread any collection to function which expects varargs, you need to transform it to the array:

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

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]));
  }
}

All these calls of printManywill print:

所有这些调用printManywill 打印:

one

two

three

It's not exactly same as spread operator, but in most cases, it's good enough.

它与扩展运算符并不完全相同,但在大多数情况下,它已经足够好了。