J'ai une exception dans une variable (non levée).
Quelle est la meilleure option?
Exception exception = someObj.getExcp();
try {
throw exception;
} catch (ExceptionExample1 e) {
e.getSomeCustomViolations();
} catch (ExceptionExample2 e) {
e.getSomeOtherCustomViolations();
}
ou
Exception exception = someObj.getExcp();
if (exception instanceof ExceptionExample1) {
exception.getSomeCustomViolations();
} else if (exception instanceof ExceptionExample2) {
exception.getSomeOtherCustomViolations();
}
Je vous conseille d'utiliser instanceof
car ce sera probablement plus rapide. Lancer une exception est une opération compliquée et coûteuse. Les JVM sont optimisées pour être rapides dans le cas où des exceptions ne pas se produisent. Les exceptions doivent être exceptionnelles.
Notez que la technique throw
ne se compilera probablement pas comme indiqué, si votre type d'exception est une exception vérifiée, le compilateur se plaindra que vous devez intercepter ce type ou le déclarer comme levé (correspondant à un else { ... }
clause si vous utilisez la technique instanceof
), qui peut être utile ou non, selon la façon dont vous souhaitez gérer les exceptions qui ne font pas partie des sous-types spécifiques.
Je déteste faire éclater la bulle de tout le monde, mais en utilisant try/catch
est plus rapide. Cela ne veut pas dire que c'est la manière "correcte", mais si la performance est la clé, c'est le gagnant. Voici les résultats du programme suivant:
Exécuter 1
Exécuter 2
Exécuter
Environnement de test
En actualisant les sous-exécutions de préchauffage de chaque exécution, la méthode instanceof
n'atteint au mieux que les performances de try/catch
. La moyenne (actualisation des échauffements) de la méthode instanceof
est de 98 ms et la moyenne de try/catch
est de 92 ms.
Veuillez noter que je n'ai pas modifié l'ordre dans lequel chaque méthode a été testée. J'ai toujours testé un bloc de instanceof
puis un bloc de try/catch
. J'aimerais voir d'autres résultats contredire ou confirmer ces résultats.
public class test {
public static void main (String [] args) throws Exception {
long start = 0L;
int who_cares = 0; // Used to prevent compiler optimization
int tests = 100000;
for ( int i = 0; i < 3; ++i ) {
System.out.println("Testing instanceof");
start = System.currentTimeMillis();
testInstanceOf(who_cares, tests);
System.out.println("instanceof completed in "+(System.currentTimeMillis()-start)+" ms "+who_cares);
System.out.println("Testing try/catch");
start = System.currentTimeMillis();
testTryCatch(who_cares, tests);
System.out.println("try/catch completed in "+(System.currentTimeMillis()-start)+" ms"+who_cares);
}
}
private static int testInstanceOf(int who_cares, int tests) {
for ( int i = 0; i < tests; ++i ) {
Exception ex = (new Tester()).getException();
if ( ex instanceof Ex1 ) {
who_cares = 1;
} else if ( ex instanceof Ex2 ) {
who_cares = 2;
}
}
return who_cares;
}
private static int testTryCatch(int who_cares, int tests) {
for ( int i = 0; i < tests; ++i ) {
Exception ex = (new Tester()).getException();
try {
throw ex;
} catch ( Ex1 ex1 ) {
who_cares = 1;
} catch ( Ex2 ex2 ) {
who_cares = 2;
} catch ( Exception e ) {}
}
return who_cares;
}
private static class Ex1 extends Exception {}
private static class Ex2 extends Exception {}
private static Java.util.Random Rand = new Java.util.Random();
private static class Tester {
private Exception ex;
public Tester() {
if ( Rand.nextBoolean() ) {
ex = new Ex1();
} else {
ex = new Ex2();
}
}
public Exception getException() {
return ex;
}
}
}
Je vous exhorte fortement à réellement utiliser un objet simple pour représenter votre "contrainte". Que ce soit une interface de marquage (par exemple Message
) ou un Java.lang.String
c'est à vous de décider. Les exceptions ne sont pas censées être utilisées comme vous le souhaitez, même si l'une ou l'autre pourrait fonctionner (je m'attendrais à ce que la seconde soit plus rapide, mais une optimisation prématurée ...).
Vous pouvez également utiliser le polymorphisme en créant une interface pour vos exceptions personnalisées qui contient la méthode getCustomViolation (). Ensuite, chaque exception personnalisée implémenterait cette interface et cette méthode.