Java 8 lambda Void参数

Java 8 lambda Void参数,java,lambda,java-8,void,Java,Lambda,Java 8,Void,假设我在Java 8中有以下功能接口: interface Action<T, U> { U execute(T t); } 接口动作{ U执行(T); } 对于某些情况,我需要一个没有参数或返回类型的操作。所以我写 大概是这样的: Action<Void, Void> a = () -> { System.out.println("Do nothing!"); }; 动作a=()->{System.out.println(“什么都不做!”);}; 然

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

interface Action<T, U> {
   U execute(T t);
}
接口动作{
U执行(T);
}
对于某些情况,我需要一个没有参数或返回类型的操作。所以我写 大概是这样的:

Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
动作a=()->{System.out.println(“什么都不做!”);};
然而,它给了我编译错误,我需要把它写成

Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
Action a=(Void v)->{System.out.println(“什么都不做!”);返回null;};
这很难看。有没有办法去掉
Void
类型参数?

lambda:

() -> { System.out.println("Do nothing!"); };
实际上表示接口的实现,如:

public interface Something {
    void action();
}
这和你定义的完全不同。这就是为什么会出现错误


既然你不能扩展你的
@functional界面,也不能引入一个全新的界面,那么我认为你没有太多的选择。但是,您可以使用
可选接口
来表示缺少某些值(返回类型或方法参数)。但是,这并不会使lambda主体变得更简单。

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

lambda表达式的计算结果与

void action() { }
而你的声明看起来

Void action(Void v) {
    //must return Void type.
}
new VoidInterface() {
    public Void action(Void v) {
        //do something
        return v;
    }
}
例如,如果您有以下接口

public interface VoidInterface {
    public Void action(Void v);
}
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);
    }

}
唯一一种可兼容的函数(实例化时)如下所示

Void action(Void v) {
    //must return Void type.
}
new VoidInterface() {
    public Void action(Void v) {
        //do something
        return v;
    }
}
缺少返回语句或参数都会导致编译器错误


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

您所追求的语法是可以使用一个小的辅助函数将
Runnable
转换为
Action
(例如,您可以将其放置在
操作中):

公共静态操作(Runnable-Runnable){
返回(v)->{
runnable.run();
返回null;
};
}
//代码中的其他地方
Action Action=Action(()->System.out.println(“foo”);

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

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

您可以为该特殊情况创建子接口:

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

在函数接口中添加静态方法

public interface VoidInterface {
    public Void action(Void v);
}
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);
    }

}

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

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
}
void notReturnsNotThrows(){};
void notReturnsThrows()引发异常{}
字符串returnsNotThrows(){return”“;}
字符串returnsThrows()引发异常{return”“;}
{
Runnable r1=this::notReturnsNotThrows;//确定
Runnable r2=this::notReturnsThrows;//错误
Runnable r3=this::returnsNotThrows;//确定
Runnable r4=this::returnsThrows;//错误
Callable c1=this::notReturnsNotThrows;//错误
Callable c2=this::notReturnsThrows;//错误
Callable c3=this::returnsNotThrows;//确定
Callable c4=this::returnsThrows;//确定
}
接口voidCallableExtendCallable扩展Callable{
@凌驾
Void call()抛出异常;
}
接口可调用{
void call()抛出异常;
}
{
voidCallableExtendCallable vcec1=this::notReturnsNotThrows;//错误
voidCallableExtendCallable vcec2=this::notReturnsThrows;//错误
voidCallableExtendCallable vcec3=this::returnsNotThrows;//错误
voidCallableExtendCallable vcec4=this::returnsThrows;//错误
VoidCallable vc1=this::notReturnsNotThrows;//确定
VoidCallable vc2=this::notReturnsThrows;//确定
VoidCallable vc3=this::returnsNotThrows;//确定
VoidCallable vc4=this::returnsThrows;//确定
}
如果不需要任何东西,但返回一些东西,请使用

如果它需要一些东西,但不返回任何东西,则使用

如果它返回一个结果并可能抛出,则使用(最类似于一般的CS术语)


如果两者都不能抛出,请使用。

我认为这张表很短,很有用:

Supplier       ()    -> x
Consumer       x     -> ()
Callable       ()    -> x throws ex
Runnable       ()    -> ()
Function       x     -> y
BiFunction     x,y   -> z
Predicate      x     -> boolean
UnaryOperator  x1    -> x2
BinaryOperator x1,x2 -> x3

正如在其他答案中所说,这个问题的合适选项是
Runnable

看看如果您需要一个操作,正如您定义的那样,这是不可能的。但是,您的第一个示例可以放入
Runnable
,这就是您正在寻找的
Runnable r=()->System.out.println(“什么都不做!”);
@BobTheBuilder我不想像那篇文章中建议的那样使用使用者。马特的回答使类型可以工作,但是调用者在得到空返回值时会做什么?你可以交叉手指,希望Java 9接受中的建议2和3!问题是你的
Something
函数不能是我的
的子类型>Action
type,我不能有两种不同的类型。技术上他可以,但他说他想避免:)这是你能得到的最干净的解决方法,依我看,so+1(或使用界面本身的静态方法)Konstantin Yovkov下面的解决方案(带有@FunctionInterface)是一个更好的解决方案,因为它不涉及泛型,也不需要额外的代码。@uthomas抱歉,我没有看到涉及
@functionanterface
的答案。他只是说,不可能扩展它…嗨,马特,对不起。我反应太快了。对于给定的问题,你的答案是完全正确的。不幸的是,我的投票被锁定了,所以我不能删除我对这个答案的-1。注二:1。除了
Runnable
操作之外,还应该使用一个自定义的
@functional接口
一种称为
副作用的东西
,2。对这样的帮助函数的需要突出显示出一些奇怪的事情正在发生,可能抽象被破坏了。例如,我这样做是为了包装“void”返回调用:
公共静态void wrapCall(Runnable r){r.run();}
。谢谢你漂亮的回答。简短而精确。不幸的是,如果它必须抛出已检查的异常,则没有帮助。如