Je voudrais deux ont deux méthodes différentes en cours d' exécution dans catch
et final
blocs. J'ai trouvé l' AutoCloseable
interface, mais je dois quelque chose à feu en cas d'exception seulement.
Comme:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
Est-il possible de le rendre plus simple? Comme je l'ai dit que je suis familier avec AutoCloseable, mais il me permet seulement avec bloc finally. Je ne peux toujours pas l'utiliser à l'intérieur des prises.
Eh bien , vous pouvez définir votre propre interface, puis une static
méthode de coureur:
public interface ErrorHandlingCloseable extends AutoCloseable {
void run() throws Exception;
void onError(Exception e);
static void execute(ErrorHandlingClosable ehc) throws Exception {
try(ErrorHandlingClosable temp = ehc) {
ehc.run();
} catch(Exception e) {
ehc.onError(e);
throw e;
}
}
}
Alors que vous pourriez alors appeler comme ceci:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});
Mais voyez-vous, il est salissant encore.
Vous pouvez même mettre en œuvre ce interface
dans votre SomeService
mais vous êtes limité que la run()
méthode toujours faire appel doSomeMessyThingsInsideDB()
.
Une autre façon similaire , mais encore serait d'utiliser Java8 et créer une aide fonctionnelle interface
:
public interface ThrowingRunnable {
void run() throws Exception;
}
Et puis un static
endroit de la méthode:
public static void execute(ThrowingRunnable action,
ThrowingRunnable onCatch,
ThrowingRunnable onFinally) throws Exception {
try(AutoCloseable ao = onFinally) {
action.run();
} catch(Exception e) {
onCatch.run();
throw e;
}
}
La partie intéressante est sans doute celle - ci: try(AutoCloseable ao = onFinally)
qui « registres » de votre onFinally
méthode à appeler quand finally
est atteint.
Cela pourrait alors être appelé comme ceci:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);