2010-01-03 6 views
1

Je veux une méthode qui peut lancer n'importe quel Throwable y compris les sous-classes d'Exception. J'ai quelque chose qui prend une exception, le stocke dans un thread local, puis appelle un class.newInstance. Cette classe ctor déclare qu'elle lance Exception puis prend le threadlocal et le lance. Le problème est que cela ne fonctionne pas pour les deux Exceptions déclarées par Class.newInstance() à savoir IllegalAccessException et InstantiationException. Im deviner toute autre méthode en utilisant une classe sun.* est juste un hack et pas vraiment fiable.Magic Lanceur d'exception sans déclarer de lancement Exception

Emballage n'est pas une option, car cela signifie que les capteurs rattrapent un type diff et c'est trop simple et ennuyeux ...

static public void impossibleThrow(final Throwable throwable) { 
    Null.not(throwable, "throwable"); 
    if (throwable instanceof RuntimeException) { 
     throw (RuntimeException) throwable; 
    } 
    if (throwable instanceof Error) { 
     throw (Error) throwable; 
    } 
    try { 
     THROW.set((Exception) throwable); 
     THROWER.newInstance(); 
    } catch (final InstantiationException screwed) { 
     throw new Error(screwed); 
    } catch (final IllegalAccessException screwed) { 
     throw new Error(screwed); 
    } finally { 
     THROW.remove(); 
    } 
} 

private final static Class<Impossible> THROWER = Impossible.class; 
private final static ThreadLocal<Exception> THROW = new ThreadLocal<Exception>(); 

static private class Impossible { 

    @SuppressWarnings("unused") 
    public Impossible() throws Exception { 
     throw THROW.get(); 
    } 
} 
+2

Je ne peux pas obtenir ce que vous essayez d'atteindre .. – Bozho

+0

Je ne peux pas imaginer pourquoi cela pourrait être utile. – duffymo

+0

Je pense que c'est juste pour m'amuser. Comment pouvez-vous lancer une exception vérifiée sans la déclarer dans une clause throws? –

Répondre

3

De Java Puzzlers (casse-tête 43):

public static void impossibleThrow(Throwable t) 
{ 
    Thread.currentThread().stop(t); // Deprecated method. 
} 

Le livre montre d'autres méthodes pour atteindre le même problème, on est une version simplifiée de la vôtre, les autres exploits d'effacement de type générique lancer un Throwable où une erreur est attendue.

+0

Va vérifier ça sonne comme un gagnant, l'emballage est trop simple et pas vraiment le même résultat. –

3

Si vous voulez une exception à bouillonner par le code ne m'y attendais pas exception alors enveloppez-le simplement dans une exception RuntimeException

} catch (RuntimeException e) { 
    throw e; // only wrap if needed 
} catch (Exception e) { 
    throw new RuntimeException("FOO went wrong", e); 
} 

N'oubliez pas de laisser le message être informatif. Un jour, vous devrez corriger un bug basé uniquement sur les informations de la trace de la pile.

3

Envelopper une exception à l'intérieur d'une exception RuntimeException (comme suggéré par Thorbjørn) est le chemin à suivre. Cependant, vous voulez généralement maintenir la trace de pile de l'excpetion originale. Voici comment:

public static void rethrow(final Throwable t) 
    { 
    if(t instanceof RuntimeException) 
     throw (RuntimeException) t; 

    RuntimeException e = new RuntimeException(t); 
    e.setStackTrace(t.getStackTrace()); 
    throw e; 
    } 
0

J'ai corrigé javac pour supprimer l'erreur, compilé impossibleThrow(), renommé le fichier source pour quelque chose qui ne se termine pas en .java (qui oblige la prochaine compilation à utiliser le .class existant) et utilisé cela.

0

Il existe une certaine validité pour cette question en tant qu'outil de débogage. Supposons que vous travaillez avec du code qui a échoué et que vous voyez qu'il (peut-être) attrape certaines exceptions et (peut-être) émet certaines exceptions. Vous pensez qu'une exception inattendue n'a pas été interceptée. Cependant, le code/système sous-jacent est trop complexe et le bogue est trop intermittent pour vous permettre de naviguer dans le débogueur. Il peut être utile d'ajouter le lancement d'une exception sans changer la méthode d'une autre manière. Dans ce cas, l'exécution de l'exception avec une exception RuntimeException ne fonctionnerait pas, car vous souhaitez que les méthodes appelantes se comportent normalement.

Questions connexes