11
votes

Quelle est la sécurité de mon reflethow?

( TARD EDIT: STROND> Cette question sera obsolète lorsque Java 7 vient, à cause du Caractéristique "Final Rethow" quel semble que ce soit ajouté .) em>


assez souvent, je me trouve dans des situations ressemblant à ceci: p> xxx pré>

in c # vous pouvez le faire comme ceci: p> xxx pré>

pour Java, il n'y a pas de bonne substitution, et puisque La proposition d'amélioration de la manipulation des exceptions a été coupée de Java 7 , on dirait que cela prendra au mieux plusieurs années jusqu'à ce que nous obtenions quelque chose comme ça. Ainsi, j'ai décidé de rouler le mien: P>

( Edit: strong> demi-un an plus tard, Rethow final est de retour , ou il semble donc qu'il semble.) p> xxx pré>

Utilisation typique: p>

public void doStuff() throws SomeException {
    initializeStuff();
    try {
        doSomeWork();
    } catch (Throwable t) {
        undoInitialize();
        Rethrow.instanceOrUnchecked(SomeException.class, t);
        // We shouldn't get past the above line as only unchecked or 
        // SomeException exceptions are thrown in the try block, but
        // we don't want to risk swallowing an error, so:
        throw new SomeException("Unexpected exception", t); 
    }
    private void doSomeWork() throws SomeException { ... }
}


1 commentaires

Vous avez une bonne justification pour attraper la jante. Ne laissez pas vous descendre. Cela ressemble beaucoup à l'utilisation de goto ", ne l'utilisez jamais, à moins que vous ne l'iez."


3 Réponses :


1
votes

Si vous êtes censé que votre inaidification se produise, vous voudrez peut-être simplement mettre ce code dans un blocage enfin, comme cela devrait être appelé à un moment donné, vous devriez peut-être toujours nettoyer.

Je suis Leery of Attraper lancé comme certaines des exceptions que je veux gérer, et certains je me connectent, comme il n'y a aucune utilité d'exceptions de passage que l'utilisateur ne peut rien faire, comme un nullpointException .

Mais, vous n'avez pas montré ce que someexception est défini comme étant défini, mais si un OutofMemoryException est lancé, votre lanceur va attraper, mais ce sera peut-être le même Tapez comme SOMException de sorte que votre wrapper soit nécessaire dans votre fonction d'échantillon, au moins lorsque je regarde la méthode instanceorunchecked

Vous voudrez peut-être écrire un test de l'unité, essayez différentes classes d'exceptions et voir ce qui fonctionne ou ne fonctionne pas comme prévu, vous pouvez donc documenter le comportement attendu.


6 commentaires

SoméException étend une exception . En ce qui concerne la disinitialisation dans enfin - Je veux seulement que l'inaidification se produise si une exception est lancée. Je pouvais bien entendu avoir un drapeau booléen initialement défini sur FALSE, puis la définir comme la dernière chose à la dernière chose dans le bloc , mais c'est un peu encombrant (et si quelqu'un ajoute du code après sa définition à vrai sans réfléchir à la manipulation d'exception?).


En outre, je l'ai testé, et cela fonctionne très bien ... Dans toutes les circonstances, j'ai pu penser, ce qui ne prouve que si j'ai réussi à écrire du code, je ne suis pas assez intelligent pour me casser =)


Avez-vous été testé avec une classe qui s'étend à DJEBLABLE, et non une exception?


@JB, je n'ai pas. Astucieux! Je devrais probablement changer la contrainte de type sur instanceorunchecked à partir d'une exception sur à s'étend lotable pour permettre aux clients de réthorner de telles abominations.


@gustafc - Juste à la recherche de cas que vous ne vous attendez probablement pas. Celui-ci est un problème pour les personnes qui enveloppent leurs appels dans les captures (exceptions) car les erreurs les plus critiques ne sont pas une exception.


@gustafc, au lieu de vérifier un drapeau booléen, essayez de vérifier la référence à l'objet que vous essayiez de créer. Si c'est null, une exception a probablement été attrapée. Et si quelqu'un ajoute du code sans mettre à jour le chèque, ils auront un objet valide ou une nullpoinpointException



1
votes

Une alternative consiste à avoir une usine qui crée une exception SOMExException uniquement si la cause est une exception vérifiée: xxx pré>

La raison pour laquelle je mets dans la valeur de retour dans la méthode est de sorte que le client peut faire quelque chose comme ceci: p> xxx pré>

de sorte que le compilateur soit dupe à ne pas nécessiter de retour après la déclaration de capture si la méthode a un type de retour, mais il jette toujours l'exception Si le client a oublié de mettre le lancer avant l'appel à la méthode d'usine. p>

L'inconvénient de ce code sur votre code est qu'il est moins portable (cela fonctionne pour la soméexception, mais pas pour une certaine exception), mais cela peut-être bien, car il ne sera pas pour chaque type d'exception que vous devez avoir une initialisation d'annulation. p>

S'il correspond à votre cas d'utilisation, vous pouvez mettre l'appel non coché dans le constructeur de SOMException et avoir le logique disponible pour toutes les sous-classes, mais cela devrait correspondre à votre projet spécifique - ce ne serait pas une bonne idée dans le cas général car cela empêcherait d'emballer ru Ntime Exceptions. P>

      public SomeException(message, cause) {
            super(message, unchecked(cause));
      }

      private static Throwable unchecked(Throwable cause) {
          if (cause instanceof Error) throw (Error) cause;
          if (cause instanceof RuntimeException) throw (RuntimeException) cause;
          return cause;
      }


1 commentaires

La fonction d'usine est belle, mais depuis que j'ai une hiérarchie d'exception (plusieurs classes s'étendant someexception ), j'ai besoin de quelque chose de plus flexible. J'aime l'intelligence de la deuxième alternative, mais je pense que c'est peut-être trop intelligent - le potentiel de maintenance du WTF semble élevé.



5
votes

Il y a un moyen de gérer cela. Le premier est ma préférence si vous n'avez pas besoin de savoir quelle était l'exception.

try {
    // do some work which might throw an exception
} catch (Throwable t) {
    // do something with t.
    Thread.currentThread().stop(t);
}


0 commentaires