I hate checked exceptions. I really do. They should have really got rid of them in Java 8. They get in the way of a lot of the new stuff; it's not a coincidence that most of the other JVM languages don't have checked exceptions.
BEGIN RANT
I have a class in which I'm overriding an abstract method:
@Override
protected Runnable createTask(Request req) {
Response resp = new Response(Errors.CANT_CONNECT);
if (req.getType() == Request.Something) {
return () -> {
try {
oneThing(req, resp);
} catch (IOException ex) {
log.error("Doing something with {}", req, ex);
} finally {
process(resp);
}
};
} else if (req.getType() == Request.SomethingElse) {
return () -> {
try {
somethingElse(req, resp);
} catch (IOException ex) {
log.error("doing something else with {}", req, ex);
} finally {
process(resp);
}
};
} else if (req.getType() == Request.YetAnotherThing) {
return () -> {
try {
anotherThing(req, resp);
} catch (IOException ex) {
log.error("Doing yet another thing with {}", req, ex);
} finally {
process(resp);
}
};
}
return null;
}
As you can see, it's very repetitive. A block is code is basically repeated 3 times with just a very small variation. An obvious opportunity to put it elsewhere, right? Something like this looks way nicer:
private Runnable execute(BiConsumer<Request, Response> m,
Request req, String msg) {
Response resp = new Response(Errores.CANT_CONNECT);
return () -> {
try {
m.accept(req, resp);
} catch (IOException ex) {
log.error(msg, ex);
} finally {
process(resp);
}
};
}
@Override
public Runnable createTask(Request req) {
if (req.getType() == Request.Something) {
return ejecutar(this::oneThing, req, "Doing something with {}");
} else if (req.getType() == Request.SomethingElse) {
return ejecutar(this::somethingElse, req, "doing something else with {}");
} else if (req.getType() == Request.YetAnotherThing) {
return ejecutar(this::anotherThing, req, "Doing yet another thing with {}");
}
return null;
}
Way nicer. Yeah.
Except I can't do this. Why not? Well, BiConsumer
doesn't throw IOException
, therefore I can't catch it. Also, I can't pass refs to my methods because they throw IOException
.
In order to do this, I need to catch IOException
inside each of my methods, only to convert it into a RuntimeException
, which I can then catch in execute
.
I really don't want to do that right now. So... ⌘+Z ⌘+Z ⌘+Z ⌘+Z ⌘+Z ⌘+Z ⌘+Z ⌘+Z ⌘+Z ⌘+Z
END RANT
Top comments (4)
You can define your own BiConsumer interface that throws checked exceptions as follows:
And also define a CheckedRunnable that propagates the exception thrown by the CheckedBiConsumer:
That way you can leave it up to the code executing the runnable what to do with the checked exception.
Tanks for the tip! Creating the CheckedBiConsumer does the trick indeed. I can't use the second one because the code I'm extending already defines that I need to return a standard
Runnable
though, but that's not a problem.This library contains many useful wrappers for Lambdas and Exceptions: github.com/jOOQ/jOOL#orgjooqlambda...
I've heard about vavr, it's worth a look.