在Java中实现递归lambda函数

在Java中实现递归lambda函数,java,recursion,lambda,Java,Recursion,Lambda,我不知道下面的事情是否可能。我希望Runnable的run()方法包含Runnable本身,即 reconnects = 3; Runnable executeAfter = () -> { if ( --reconnects < 0 ) { println("%nStop using port %d.", this.port); //... } else { // try to reconnect println("%

我不知道下面的事情是否可能。我希望
Runnable
run()
方法包含
Runnable
本身,即

reconnects = 3;
Runnable executeAfter = () -> {
    if ( --reconnects < 0 ) {
        println("%nStop using port %d.", this.port);
        //...
    } else { // try to reconnect
        println("%nReconnecting...");
        cmdRun = new CmdRun(command, executeAfter);
        (new Thread(cmdRun)).start();
        //...
    }
};
重新连接=3;
Runnable executeAfter=()->{
如果(--重新连接<0){
println(“%n停止使用端口%d.”,此端口);
//...
}否则{//请尝试重新连接
println(“%n正在连接…”);
cmdRun=新的cmdRun(命令,executeAfter);
(新线程(cmdRun)).start();
//...
}
};

这样的事情可能吗?如果是,怎么做?(
CmdRun
的构造函数是
CmdRun(String命令,Runnable executeAfter)

最简单的方法可能是将lambda的内容放在方法中,并使用方法引用定义可运行的。

最简单的方法可能是将lambda的内容放在方法中,并使用方法引用定义可运行的。

可运行的run()不能包含自引用,因为它是非法的。 我不太确定你想要实现什么,但类似的事情应该会奏效:

class CmdRun implements Runnable {

    final Object command;
    final Runnable runnable;

    final Runnable executeAfter = () -> {
        if ( --reconnects < 0 ) {
            System.out.println("%nStop using port %d." + port);
            //...
        } else { // try to reconnect
            System.out.println("%nReconnecting...");
            CmdRun cmdRun = new CmdRun(command);
            (new Thread(cmdRun)).start();
            //...
        }
    };

    public CmdRun(Object command) {
        this.command = command;
        this.runnable = executeAfter;
    }

    @Override
    public void run() {
        runnable.run();
    }
}
class CmdRun实现可运行{
最终目标命令;
最终可运行;
最终可运行的executeAfter=()->{
如果(--重新连接<0){
System.out.println(“%n停止使用端口%d.”+端口);
//...
}否则{//请尝试重新连接
System.out.println(“%nReconnection…”);
CmdRun CmdRun=new CmdRun(命令);
(新线程(cmdRun)).start();
//...
}
};
公共CmdRun(对象命令){
this.command=命令;
this.runnable=executeAfter;
}
@凌驾
公开募捐{
runnable.run();
}
}
Runnable的run()不能包含自引用,因为它是非法的。 我不太确定你想要实现什么,但类似的事情应该会奏效:

class CmdRun implements Runnable {

    final Object command;
    final Runnable runnable;

    final Runnable executeAfter = () -> {
        if ( --reconnects < 0 ) {
            System.out.println("%nStop using port %d." + port);
            //...
        } else { // try to reconnect
            System.out.println("%nReconnecting...");
            CmdRun cmdRun = new CmdRun(command);
            (new Thread(cmdRun)).start();
            //...
        }
    };

    public CmdRun(Object command) {
        this.command = command;
        this.runnable = executeAfter;
    }

    @Override
    public void run() {
        runnable.run();
    }
}
class CmdRun实现可运行{
最终目标命令;
最终可运行;
最终可运行的executeAfter=()->{
如果(--重新连接<0){
System.out.println(“%n停止使用端口%d.”+端口);
//...
}否则{//请尝试重新连接
System.out.println(“%nReconnection…”);
CmdRun CmdRun=new CmdRun(命令);
(新线程(cmdRun)).start();
//...
}
};
公共CmdRun(对象命令){
this.command=命令;
this.runnable=executeAfter;
}
@凌驾
公开募捐{
runnable.run();
}
}

简短回答:

长答案: 你的代码会给你一个语法错误。为什么?lambda内部使用的
executeAfter
未初始化;它仅在lambda定义的完整主体之后初始化

例如,考虑下面的例子。

int i;
sum(i, 5); // Syntax error!! Variable i is not initialized...
你的情况类似。在lambda内部,
executeAfter
未初始化。如上所述,它仅在lambda定义的整个主体之后初始化


节点的另一件事是变量
reconnects
必须是final,才能在lambda中使用。如果它是最终变量,则不能在If条件内对其使用
--
运算符

简短回答:

长答案: 你的代码会给你一个语法错误。为什么?lambda内部使用的
executeAfter
未初始化;它仅在lambda定义的完整主体之后初始化

例如,考虑下面的例子。

int i;
sum(i, 5); // Syntax error!! Variable i is not initialized...
你的情况类似。在lambda内部,
executeAfter
未初始化。如上所述,它仅在lambda定义的整个主体之后初始化


节点的另一件事是变量
reconnects
必须是final,才能在lambda中使用。如果它是最终变量,则不能在If条件内对其使用
--
运算符

这里必须有兰姆达吗?如果不是,切换到旧的等效语法应该很简单:

例如:

public class TestLambda {
    static int count = 0;
    public static void main(String[] args) {
        // lambda not going to work
        //Runnable foo = () -> { if (count < 5) { call(foo); } };
        // nor
        //Runnable foo = () -> { if (count < 5) { call(this); } };

        // using old way of anonymous inner class will work
        Runnable foo = new Runnable() {
            @Override public void run() {
                if (count < 5) {
                    call(this);
                }
            }
        };

        foo.run();
    }

    public static void call(Runnable action) {
        count++;
        System.out.println("in call " + count);
        action.run();
    }
}
公共类TestLambda{
静态整数计数=0;
公共静态void main(字符串[]args){
//lambda不工作了
//runnablefoo=()->{if(count<5){call(foo);};
//也不是
//runnablefoo=()->{if(count<5){调用(this);};
//使用匿名内部类的旧方法将起作用
Runnable foo=new Runnable(){
@重写公共无效运行(){
如果(计数小于5){
叫(这个);
}
}
};
foo.run();
}
公共静态无效调用(可运行操作){
计数++;
系统输出打印项次(“输入呼叫”+计数);
action.run();
}
}

这里必须有lambda吗?如果不是,切换到旧的等效语法应该很简单:

例如:

public class TestLambda {
    static int count = 0;
    public static void main(String[] args) {
        // lambda not going to work
        //Runnable foo = () -> { if (count < 5) { call(foo); } };
        // nor
        //Runnable foo = () -> { if (count < 5) { call(this); } };

        // using old way of anonymous inner class will work
        Runnable foo = new Runnable() {
            @Override public void run() {
                if (count < 5) {
                    call(this);
                }
            }
        };

        foo.run();
    }

    public static void call(Runnable action) {
        count++;
        System.out.println("in call " + count);
        action.run();
    }
}
公共类TestLambda{
静态整数计数=0;
公共静态void main(字符串[]args){
//lambda不工作了
//runnablefoo=()->{if(count<5){call(foo);};
//也不是
//runnablefoo=()->{if(count<5){调用(this);};
//使用匿名内部类的旧方法将起作用
Runnable foo=new Runnable(){
@重写公共无效运行(){
如果(计数小于5){
叫(这个);
}
}
};
foo.run();
}
公共静态无效调用(可运行操作){
计数++;
系统输出打印项次(“输入呼叫”+计数);
action.run();
}
}

实际上,如果您不介意引入新的界面(或者如果您更经常地需要此类功能),您可以使用以下功能:

@FunctionalInterface
interface RecursiveRunnable extends Runnable {
    default void run() {
        run(this);
    }
    public void run(RecursiveRunnable runnable);
}
这将允许您递归调用runnable,例如:

int maxTries = 3;
AtomicInteger counter = new AtomicInteger();
RecursiveRunnable foo = runnable -> {
    if (counter.getAndIncrement() < maxTries) {
        println("Reconnecting... %n");
        runnable.run(); // same as: runnable.run(runnable)
    } else {
        println("Stop using port %d%n", port);
    }
};
int最大值