Reputation: 1332
I don't know if the following thing is possible. I would like a Runnable
's run()
method to contain the Runnable
itself, i.e.
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();
//...
}
};
Is something like this even possible? If so, how? (CmdRun
's constructor is CmdRun(String command, Runnable executeAfter)
)
Upvotes: 1
Views: 775
Reputation: 23252
Actually if you don't mind to introduce a new interface (or if you require such functionality more often), you could use the following:
@FunctionalInterface
interface RecursiveRunnable extends Runnable {
default void run() {
run(this);
}
public void run(RecursiveRunnable runnable);
}
This will now allow you to recursively call the runnable, e.g.:
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);
}
};
Upvotes: 1
Reputation: 40036
Is lambda a must here? If not, switching to older equivalent syntax should be simple:
An example:
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();
}
}
Upvotes: 2
Reputation: 25
Short answer: No.
Long answer:
Your code will give you a syntax error. Why? The executeAfter
used inside the lambda is not initialized; it is only initialized after the full body of the lambda definition.
For example, consider the below example.
int i;
sum(i, 5); // Syntax error!! Variable i is not initialized...
Your case is similar. Inside the lambda, executeAfter
is not initialized. As stated above, it is only initialized after the full body of the lambda's definition.
One additional thing to node is that the variable reconnects
must be a final in order to be used inside the lambda. If it is a final variable, then you cannot use the --
operator on it inside your if condition.
Upvotes: 1
Reputation: 1750
The Runnable's run() can not contain a self reference as its illegal. Im not exactly sure what you are trying to achieve but something like this should work :
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();
}
}
Upvotes: 1
Reputation: 328598
The easiest way is probably to put the content of your lambda in a method and use a method reference to define your Runnable.
Upvotes: 1