3

I am trying to initialize an array of Runnables and then run their code. I need the initialization be as readable as possible and therefore I am using a Lambda expression for that. Now I don't know how to solve the problem with exceptions. If some code inside of the Runnables throws checked exception I would like to wrap it automatically into a RuntimeException but without putting the try/catch logic into every Runnable body.

The code looks like this:

public void addRunnable(Runnable ... x); // adds a number of Runnables into an array
...
addRunnable(
   ()->{
       some code;
       callMethodThrowsException();  // this throws e.g. IOException
   },

   ()->{
       other code;
   }
   // ... and possibly more Runnables here
);

public void RunnableCaller(List<Runnable> runnables) {
    // Now I want to execute the Runnables added to the array above
    // The array gets passed as the input argument "runnables" here
    for(Runnable x: runnables) {
        try {
            x.run();
        } catch(Exception e) { do some exception handling }
    }
}

The code does not compile because callMethodThrowsException throws a checked exception and Runnable does not so I would have to insert a try/catch block INSIDE of the Runnable definition. The try/catch block would make that thing much less convenient since I would have to put it into each Runnable body declaration which would be hard to read and unpleasant to write. Also I could create my own Runnable class that throws exception but then I cannot use the Lambda expression ()-> which makes it short and readable instead of doing

new ThrowingRunnable() { public void run() throws Exception { some code; } }

Is there a way how to define my own functional interface that would solve this issue so that I can use the same code but exceptions will be wrapped into e.g. RuntimeExceptions or so? I have a full control about the calling code so it is no problem catching the exceptions there, I only need a very readable way of writing code that will be executed later.

I saw this topic Java 8 Lambda function that throws exception? but I did not figure out how to solve my problem from that, I am not very familiar with functional interfaces. May be someone could help, thanks.

TomFT
  • 133
  • 1
  • 13

1 Answers1

2

Lambdas are not only for interfaces provided by the JVM. They can be used for every interface that exactly defines one and only one abstract method. So you can yourself create an interface, you named it already:

public interface ThrowingRunnable{
    void run() throws Exception;
}

And then replace the Parameter type in the addRunnable method:

public void addRunnable(ThrowingRunnable... runnables){ ... }

Which then lets this compile:

addRunnable(
   ()->{
       some code;
       callMethodThrowsException();  // this throws e.g. IOException
   },

   ()->{
       other code;
   }
   // ... and possibly more Runnables here
);
Lino
  • 19,604
  • 6
  • 47
  • 65
  • 1
    now having a `List` you can't add a `Runnable` to that `List` (not a lambda or method reference, but an instance of that) – Eugene Aug 22 '18 at 12:40
  • @Eugene that is correct. But from the current question I can't really find out if OP will accept runnables or will always create them himself by using lambdas – Lino Aug 22 '18 at 12:44
  • it does not matter IMO, someone might want to add an instance that implements `Runnable` (well, if I would see that method this is what I would think would be possible), but that would be impossible now – Eugene Aug 22 '18 at 12:49
  • @Eugene one could make an overload, which would wrap the `Runnable`s and then delegate them to the other method, somewhat like this: `ThrowingRunnable r = runnable::run;` – Lino Aug 22 '18 at 12:59
  • right, you can do that, no questions here. but now you have an extra indirection, probably just a matter of taste – Eugene Aug 22 '18 at 13:07
  • 1
    Shouldn’t ThrowingRunnable be annotated with @FunctionalInterface? – Stefan Großmann Aug 22 '18 at 13:28
  • @StefanGroßmann It *can* be annotated, but there is no need. See this other [question](https://stackoverflow.com/questions/36881826/what-is-use-of-functional-interface-in-java-8/36882003) for detailed information – Lino Aug 22 '18 at 13:33
  • Ah, great, I learned something new, fine. Did not expect the solution is so easy. Very good, thanks. – TomFT Aug 23 '18 at 12:59