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;};
这是丑陋的。 有没有什么办法摆脱Void
types的参数?
你所追求的语法可以通过一个辅助函数来实现,这个辅助函数可以将一个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 }