Java 8 lambda无效参数

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

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

对于某些情况,我需要一个没有参数或返回types的动作。 所以我写这样的东西:

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

不过,它给我编译错误,我需要把它写成

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

这是丑陋的。 有没有什么办法摆脱Voidtypes的参数?

你所追求的语法可以通过一个辅助函数来实现,这个辅助函数可以将一个Runnable转换成Action<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")); 

使用Supplier如果它不需要。

使用Consumer如果它没有返回

如果两者都不使用,则使用Runnable

拉姆达:

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

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

 public interface Something { void action(); } 

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

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

您可以为该特殊情况创build一个子接口:

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

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

结果是使用起来简单多了:

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

这是不可能的。 具有非void返回types的函数(即使它是Void )必须返回一个值。 但是,您可以将Action方法添加到Action ,以便“创build”一个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; } } 

这将允许你写下面的内容:

 // 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)); 

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

你的lambdaexpression式完全按照

 void action() { } 

而你的声明看起来像

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

作为一个例子,如果你有以下接口

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

唯一types的function(虽然实例化)将是兼容性看起来像

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

并且缺乏返回语句或参数会给你一个编译器错误。

因此,如果你声明了一个带参数的函数并返回一个函数,我认为不可能把它转换成上面没有提到的函数。

在你的function界面中添加一个静态方法

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

产量

 Do nothing! 

只是为了引用哪个函数接口可以用于方法引用的情况下方法抛出和/或返回一个值。

 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 }