简体   繁体   中英

Is there a standard Java 8 FunctionalInterface for a block throwing a checked exception?

Callable throws Exception, Runnable doesn't.

Is there anything standard that looks like

@FunctionalInterface
public interface TypedBlock<E extends Exception> {
    public void run() throws E;
}

No, there is no built in functionality as I know. But you can use an external library for that (and many other cool features).

You can either use JOOL , where you can use the Unchecked class for this.

The example from there page demonstrates this with an IOException

Arrays.stream(dir.listFiles()).forEach(
    Unchecked.consumer(file -> { System.out.println(file.getCanonicalPath()); })
);

Another (and in my opinion better) approach would be to use a functional designed library like Functionaljava .

A good approach would be to wrap your task in a Validation to decide afterwards, if the result was successful. This could look like this:

TypedBlock<IOException> foo = ...;

// do your work
final Validation<IOException, Unit> validation = Try.f(() -> {
  foo.run();
  return Unit.unit(); // Unit equals nothing in functional languages
})._1();

// check if we got a failure
if (validation.isFail()) {
  System.err.println("Got err " + validation.fail());
}

// check for success
if (validation.isSuccess()) {
  System.out.println("All was good :-)");
}

// this will just print out a message if we got no error
validation.forEach(unit -> System.out.println("All was good"));

There is java.lang.AutoCloseable which has a ()->{} throws Exception signature, however, it is burden with a predefined semantic. So for an ad-hoc use it might be suitable but when you design an API, I recommend defining your own interface .

Note that your specialized interface could still extend Callable<Void> to be a standard interface :

interface Block<E extends Exception> extends Callable<Void>{
    void run() throws E;
    @Override default Void call() throws E { run(); return null; }
    /** This little helper method avoids type casts when a Callable is expected */
    static <T extends Exception> Block<T> make(Block<T> b) { return b; }
}

This way you can use your Block interface with existing APIs:

// Example
ExecutorService e=Executors.newSingleThreadExecutor();
try {
    e.submit(Block.make(()->{ throw new IOException("test"); })).get();
} catch (InterruptedException ex) {
    throw new AssertionError(ex);
} catch (ExecutionException ex) {
    System.out.println("received \""+ex.getCause().getMessage()+'"');
}
e.shutdown();

Note the trick with the static method Block.make . Without it you would have to cast the lambda expression to (Block<IOException>) instead of profiting from the improved type inference. This is only necessary where a Callable is expected, for your own API where a Block is expected, you can use lambda expressions and method references directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM