Java 8 lambda 空参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29945627/
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-11 08:51:30  来源:igfitidea点击:

Java 8 lambda Void argument

javalambdajava-8void

提问by Wickoo

Let's say I have the following functional interface in Java 8:

假设我在 Java 8 中有以下功能接口:

interface Action<T, U> {
   U execute(T t);
}

And for some cases I need an action without arguments or return type. So I write something like this:

在某些情况下,我需要一个没有参数或返回类型的操作。所以我写了这样的东西:

Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };

However, it gives me compile error, I need to write it as

但是,它给了我编译错误,我需要将其写为

Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};

Which is ugly. Is there any way to get rid of the Voidtype parameter?

这是丑陋的。有没有办法摆脱Void类型参数?

采纳答案by Matt

The syntax you're after is possible with a little helper function that converts a Runnableinto Action<Void, Void>(you can place it in Actionfor example):

你以后的语法可能与一个小帮手功能,其转换RunnableAction<Void, Void>(你可以将它放在Action为例):

public static Action<Void, Void> action(Runnable runnable) {
    return (v) -> {
        runnable.run();
        return null;
    };
}

// Somewhere else in your code
 Action<Void, Void> action = action(() -> System.out.println("foo"));

回答by Konstantin Yovkov

The lambda:

拉姆达:

() -> { System.out.println("Do nothing!"); };

actually represents an implementation for an interface like:

实际上代表了一个接口的实现,如:

public interface Something {
    void action();
}

which is completely different than the one you've defined. That's why you get an error.

这与您定义的完全不同。这就是为什么你会得到一个错误。

Since you can't extend your @FunctionalInterface, nor introduce a brand new one, then I think you don't have much options. You can use the Optional<T>interfaces to denote that some of the values (return type or method parameter) is missing, though. However, this won't make the lambda body simpler.

既然你不能扩展你的@FunctionalInterface,也不能引入一个全新的,那么我认为你没有太多选择。不过,您可以使用Optional<T>接口来表示某些值(返回类型或方法参数)丢失。但是,这不会使 lambda 主体更简单。

回答by pnadczuk

I don't think it is possible, because function definitions do not match in your example.

我认为这是不可能的,因为函数定义在您的示例中不匹配。

Your lambda expression is evaluated exactly as

您的 lambda 表达式的计算方式完全相同

void action() { }

whereas your declaration looks like

而你的声明看起来像

Void action(Void v) {
    //must return Void type.
}

as an example, if you have following interface

例如,如果您有以下界面

public interface VoidInterface {
    public Void action(Void v);
}

the only kind of function (while instantiating) that will be compatibile looks like

唯一一种兼容的函数(在实例化时)看起来像

new VoidInterface() {
    public Void action(Void v) {
        //do something
        return v;
    }
}

and either lack of return statement or argument will give you a compiler error.

并且缺少 return 语句或参数会给你一个编译器错误。

Therefore, if you declare a function which takes an argument and returns one, I think it is impossible to convert it to function which does neither of mentioned above.

因此,如果您声明一个接受一个参数并返回一个参数的函数,我认为不可能将其转换为不执行上述任何一项的函数。

回答by fabian

That is not possible. A function that has a non-void return type (even if it's Void) has to return a value. However you could add static methods to Actionthat allows you to "create" a Action:

这是不可能的。具有非 void 返回类型(即使它是Void)的函数必须返回一个值。但是,您可以添加静态方法以Action允许您“创建”一个Action

interface Action<T, U> {
   U execute(T t);

   public static Action<Void, Void> create(Runnable r) {
       return (t) -> {r.run(); return null;};
   }

   public static <T, U> Action<T, U> create(Action<T, U> action) {
       return action;
   } 
}

That would allow you to write the following:

这将允许您编写以下内容:

// create action from Runnable
Action.create(()-> System.out.println("Hello World")).execute(null);
// create normal action
System.out.println(Action.create((Integer i) -> "number: " + i).execute(100));

回答by Jord?o

You can create a sub-interface for that special case:

您可以为这种特殊情况创建一个子接口:

interface Command extends Action<Void, Void> {
  default Void execute(Void v) {
    execute();
    return null;
  }
  void execute();
}

It uses a default methodto override the inherited parameterized method Void execute(Void), delegating the call to the simpler method void execute().

它使用默认方法覆盖继承的参数化方法Void execute(Void),将调用委托给更简单的方法void execute()

The result is that it's much simpler to use:

结果是使用起来要简单得多:

Command c = () -> System.out.println("Do nothing!");

回答by MCHAppy

Add a static method inside your functional interface

在您的功能接口中添加一个静态方法

package example;

interface Action<T, U> {
       U execute(T t);
       static  Action<Void,Void> invoke(Runnable runnable){
           return (v) -> {
               runnable.run();
                return null;
            };         
       }
    }

public class Lambda {


    public static void main(String[] args) {

        Action<Void, Void> a = Action.invoke(() -> System.out.println("Do nothing!"));
        Void t = null;
        a.execute(t);
    }

}

Output

输出

Do nothing!

回答by SlavaL

Just for reference which functional interface can be used for method reference in cases method throws and/or returns a value.

仅供参考,在方法抛出和/或返回值的情况下,哪个功能接口可用于方法引用。

void notReturnsNotThrows() {};
void notReturnsThrows() throws Exception {}
String returnsNotThrows() { return ""; }
String returnsThrows() throws Exception { return ""; }

{
    Runnable r1 = this::notReturnsNotThrows; //ok
    Runnable r2 = this::notReturnsThrows; //error
    Runnable r3 = this::returnsNotThrows; //ok
    Runnable r4 = this::returnsThrows; //error

    Callable c1 = this::notReturnsNotThrows; //error
    Callable c2 = this::notReturnsThrows; //error
    Callable c3 = this::returnsNotThrows; //ok
    Callable c4 = this::returnsThrows; //ok

}


interface VoidCallableExtendsCallable extends Callable<Void> {
    @Override
    Void call() throws Exception;
}

interface VoidCallable {
    void call() throws Exception;
}

{
    VoidCallableExtendsCallable vcec1 = this::notReturnsNotThrows; //error
    VoidCallableExtendsCallable vcec2 = this::notReturnsThrows; //error
    VoidCallableExtendsCallable vcec3 = this::returnsNotThrows; //error
    VoidCallableExtendsCallable vcec4 = this::returnsThrows; //error

    VoidCallable vc1 = this::notReturnsNotThrows; //ok
    VoidCallable vc2 = this::notReturnsThrows; //ok
    VoidCallable vc3 = this::returnsNotThrows; //ok
    VoidCallable vc4 = this::returnsThrows; //ok
}

回答by x1a0

Use Supplierif it takes nothing, but returns something.

使用Supplier如果它需要什么,但回报的东西。

Use Consumerif it takes something, but returns nothing.

Consumer如果它需要一些东西,但什么都不返回,请使用。

Use Callableif it returns a result and might throw (most akin to Thunkin general CS terms).

使用Callable如果它返回一个结果,并可能会抛出(最类似于Thunk一般的CS而言)。

Use Runnableif it does neither and cannot throw.

使用Runnable如果它既不并不能扔。