Java 8:具有可变参数的Lambda [英] Java 8: Lambda with variable arguments

查看:205
本文介绍了Java 8:具有可变参数的Lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方法来调用多个参数方法,但使用 lambda 构造。在文档中,据说 lambda 只有在可以映射到功能界面时才可用。

I am looking for a way to invoke multiple argument methods but using a lambda construct. In the documentation it is said that lambda is only usable if it can map to a functional interface.

我想要做类似的事情:

test((arg0, arg1) -> me.call(arg0, arg1));
test((arg0, arg1, arg2) -> me.call(arg0, arg1, arg2));
...

如果没有定义10个接口,有没有办法优雅地做到这一点,每个参数计数一个?

Is there any way one can do this elegantly without defining 10 interfaces, one for each argument count?

更新

我使用多个接口扩展自一个非方法接口,我重载该方法。

I use multiple interfaces extending from a non-method interface and I overload the method.

两个参数的示例:

interface Invoker {}
interface Invoker2 extends Invoker { void invoke(Object arg0, Object arg1);}
void test(Invoker2 invoker, Object ... arguments) {
    test((Invoker)invoker, Object ... arguments);
}

void test(Invoker invoker, Object ... arguments) {
    //Use Reflection or whatever to access the provided invoker
}

我希望有可能用一个解决方案替换10个调用者接口和10个重载方法。

I hope for a possibility to replace the 10 invoker interfaces and the 10 overloaded methods with a single solution.

我有一个合理的用例,请不要问诸如你为什么要做这样的事情?和你要解决的问题是什么?等问题。那。只知道我已经考虑过这个问题,这是一个我试图解决的合法问题。

I have a reasonable use case and please do not ask questions like 'Why would you do such a thing?' and 'What is the problem you are trying to solve?' or anything like that. Just know that I have thought this through and this is a legitimate problem I'm try to solve.

很抱歉给调用者添加了混乱,但事实上它实际上是什么在我当前的用例中调用(测试构造函数合同)。

Sorry to add confusion calling it invoker but it is actually what it is called in my current use case (testing constructor contracts).

基本上,如上所述,考虑在 lambda 中使用不同数量属性的方法。

Basically, as stated above, think about a method that works with a different number of attributes within the lambda.

推荐答案

我目前使用的最终解决方案是定义接口层次结构(如问题中所述)并使用默认方法来避免失败。伪代码如下所示:

The final solution I currently use is defining a hierarchy of interfaces (as stated in the question) and use default methods to avoid failure. Pseudo code looks like this:

interface VarArgsRunnable {
     default void run(Object ... arguments) {
          throw new UnsupportedOperationException("not possible");
     }
     default int getNumberOfArguments() {
          throw new UnsupportedOperationException("unknown");
     }
}

以及例如四个参数的接口:

and a interface for four arguments for instance:

@FunctionalInterface
interface VarArgsRunnable4 extends VarArgsRunnable {
     @Override
     default void run(Object ... arguments) {
          assert(arguments.length == 4);
          run(arguments[0], arguments[1], arguments[2], arguments[3]);
     }

     void run(Object arg0, Object arg1, Object arg2, Object arg3, Object arg4);

     @Override
     default int getNumberOfArguments() {
          return 4;
     }
}

定义了从VarArgsRunnable0到VarArgsRunnable10的11个接口重载方法变得非常简单。

Having defined 11 interfaces from VarArgsRunnable0 to VarArgsRunnable10 overloading a method becomes quite easy.

public void myMethod(VarArgsRunnable runnable, Object ... arguments) {
     runnable.run(arguments);
}

由于Java无法通过找到VarArgsRunnable的正确扩展功能接口来组成Lambda通过使用类似 instance.myMethod((index,value) - > doSomething(to(index),to(value)),10,value)一个需要使用正确的接口重载方法。

Since Java can not compose a Lambda by finding the correct extended functional interface of VarArgsRunnable by using something like instance.myMethod((index, value) -> doSomething(to(index), to(value)), 10, "value") one need to overload the method using the correct interface.

public void myMethod(VarArgsRunnable2 runnable, Object arg0, Object arg1) {
    myMethod((VarArgsRunnable)runnable, combine(arg0, arg1));
}

private static Object [] combine(Object ... values) {
    return values;
}

因为这需要使用 to(...)可以使用Generics进行参数化以避免这种情况。

Since this requires to cast Object to any appropriated type using to(...) one can go for parameterization using Generics in order to avoid this usage.

-method看起来像这样:
public static T to(Object value){
return(T)value; //抑制此警告
}

The to-method looks like this: public static T to(Object value) { return (T)value; //Supress this warning }

这个例子很蹩脚但我用它来调用一个方法,多个参数是所有潜在组合的排列(用于测试)目的)如:

The example is lame but I use it to call a method with multiple arguments being a permutation of all potential combinations (for testing purposes) like:

run((index, value) -> doTheTestSequence(index, value), values(10, 11, 12), values("A", "B", "C"));

所以这条小行会运行6次调用。所以你看到这是一个很好的帮手,能够在一行中测试多个东西而不是定义更多东西,或者在TestNG中使用多个方法等等......

So this little line runs 6 invocations. So you see this is a neat helper being able to test multiple stuff in a single line instead of defining a lot more or use multiple methods in TestNG and whatever... .

PS:不需要使用反射是一件非常好的事情,因为它不会失败并且非常可以保存参数。

PS: Having no need to use reflections is quite a good thing, since it can not fail and is quite save argument count wise.

这篇关于Java 8:具有可变参数的Lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆