87 votes

Existe-t-il un moyen de faire en sorte que la fonction run() de Runnable lève une exception ?

Une méthode que j'appelle dans exécuter() dans une classe qui implémente Runnable ) est conçu pour lever une exception.

Mais le compilateur Java ne me laisse pas faire et me suggère de l'entourer de try/catch.

Le problème est qu'en l'entourant d'un try/catch, je rends ce particulier exécuter() inutile. I do veut lancer cette exception.

Si je spécifie throws pour exécuter() lui-même, le compilateur se plaint que Exception is not compatible with throws clause in Runnable.run() .

D'ordinaire, je suis tout à fait d'accord pour ne pas laisser exécuter() lancer une exception. Mais j'ai une situation unique dans laquelle je dois avoir cette fonctionnalité.

Comment puis-je contourner cette limitation ?

91voto

Alex Points 15303

Vous pouvez utiliser un Callable au lieu de le soumettre à un ExecutorService et attendre le résultat avec FutureTask.isDone() retourné par le ExecutorService.submit() .

Lorsque isDone() retourne vrai, vous appelez FutureTask.get() . Maintenant, si votre Callable a lancé un Exception puis FutureTask.get() lancera un Exception aussi et l'original Exception à laquelle vous pourrez accéder en utilisant Exception.getCause() .

37voto

Alexander Pogrebnyak Points 24964

Si vous voulez passer une classe qui implémente Runnable dans le Thread voir la réponse d'Ernest Friedman-Hill qui explique pourquoi faire autrement est une mauvaise idée.

J'ai l'intuition, cependant, que vous voulez appeler run directement dans votre code, afin que votre code d'appel puisse traiter l'exception.

La réponse à ce problème est simple. N'utilisez pas Runnable de la bibliothèque Thread, mais créez plutôt votre propre interface avec la signature modifiée qui permet de lever une exception vérifiée, par exemple

public interface MyRunnable
{
    void myRun ( ) throws MyException;
}

Vous pouvez même créer un adaptateur qui convertit cette interface en une véritable Runnable (en gérant les exceptions vérifiées) qui peut être utilisé dans le cadre de Thread.

27voto

Ernest Friedman-Hill Points 56605

Si run() a lancé une exception vérifiée, qu'est-ce qui la rattraperait ? Il n'y a aucun moyen pour vous d'enfermer cette run() dans un handler, puisque vous n'écrivez pas le code qui l'invoque.

Vous pouvez attraper votre exception vérifiée dans le run() et lancer une exception nonchiffrée (c'est-à-dire, RuntimeException ) à sa place. Cela mettra fin au thread avec une trace de la pile ; c'est peut-être ce que vous recherchez.

Si vous voulez plutôt que votre run() pour signaler l'erreur quelque part, alors vous pouvez simplement fournir une méthode de rappel pour la méthode run() de la méthode catch à appeler ; cette méthode pourrait stocker l'objet d'exception quelque part, et le thread intéressé pourrait alors trouver l'objet à cet endroit.

21voto

erickson Points 127945

Oui, il existe un moyen de lancer un vérifié exception de la run() méthode, mais c'est si terrible que je ne la partagerai pas.

Voici ce que vous pouvez faire à la place ; cela utilise le même mécanisme qu'une exception d'exécution :

@Override
public void run() {
  try {
    /* Do your thing. */
    ...
  } catch (Exception ex) {
    Thread t = Thread.currentThread();
    t.getUncaughtExceptionHandler().uncaughtException(t, ex);
  }
}

Comme d'autres l'ont noté, si votre run() est en réalité la cible d'une méthode Thread il est inutile de lever une exception parce qu'elle est inobservable ; lever une exception a le même effet que de ne pas lever d'exception (aucun).

Si ce n'est pas un Thread la cible, n'utilisez pas Runnable . Par exemple, peut-être Callable est mieux adapté.

10voto

Sina Madani Points 532
@FunctionalInterface
public interface CheckedRunnable<E extends Exception> extends Runnable {

    @Override
    default void run() throws RuntimeException {
        try {
            runThrows();
        }
        catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    void runThrows() throws E;

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X