web-dev-qa-db-fra.com

Corriger les erreurs Java

J'ai entendu dire que saisir Java.lang.Error était considéré comme une mauvaise pratique. Je charge actuellement un fichier .dll dont la présence n'est pas garantie sur PATH, et j'aimerais passer à un emplacement configuré par l'utilisateur dans le cas où ce n'est pas. 

try {
    System.loadLibrary("HelloWorld");
} catch(UnsatisfiedLinkError ule){
    System.load("C:/libraries/HelloWorld.dll");
}

Existe-t-il une meilleure façon de le faire? Ou attraper la UnsatisfiedLinkError ici acceptable?

21
Jainathan Leung

Outre les conseils sur la manière de résoudre techniquement le problème, j'aimerais prendre un moment pour expliquer pourquoi cela est considéré comme une "mauvaise pratique".

Commençons par clarifier ce qu'est la classe Error.


En Java, les erreurs et les exceptions (qui sont les principaux types) sont renvoyées. Le lancement de l'un des éléments ci-dessus est effectué à l'aide du mot clé throw. Chaque classe qui étend le Java.lang.Throwable de base peut être levée.

Deux classes héritent de la classe de base Throwable: Exception et Error. La différence entre ces deux est expliquée dans leurs documentations:

Un Erreur est une sous-classe de Throwable que indique des problèmes graves Qu'une application raisonnable ne devrait pas tenter de résoudre. La plupart De telles erreurs sont des conditions anormales. [...]

La source

La classe Exception et ses sous-classes sont une forme de Throwable Que indique les conditions qu'une application raisonnable pourrait vouloir attraper.

La source


Comme expliqué ci-dessus, les erreurs et les exceptions sont séparées en raison de leurs origines différentes. Un Error indique normalement un problème, dont l'application ne peut pas récupérer. Par conséquent, ils ne devraient pas être attrapés.

Il en va de même pour une RuntimeException, mais elle est utilisée pour indiquer un problème avec une couche de haut niveau (par exemple, des méthodes). Alors que Error indique un problème de bas niveau (par exemple, le temps d'exécution).


Donc, maintenant que vous avez compris que vous devez ne capturer que les exceptions et les erreurs que vous pouvez récupérer , la réponse à votre question devrait être claire.

Oui, il est parfaitement raisonnable d’accepter la UnsatisfiedLinkError, car votre application peut en récupérer.


J'ai couvert ce qui précède (plus en détail et avec des exemples) et des informations détaillées dans un article sur mon blog .

28
Lukas Knuth

Vous ne devez détecter les erreurs que dans des cas très spécifiques. Attrapez et erreur seulement si vous avez exploré toutes les autres possibilités. Je suis tout à fait d'accord avec tout ce que Lukas Knuth a dit. Mais j’ai un petit ajout. Si vous voulez détecter un type d’erreur, assurez-vous de détecter les erreurs dans un champ aussi étroit que possible. De même, si possible, assurez-vous que les méthodes sur lesquelles vous détectez des erreurs sont déclarées comme finales. La raison en est que la détection des erreurs peut généralement conduire à des programmes très instables. Considérez que vous attrapez une erreur sur une méthode qui est ensuite étendue pour appeler d'autres méthodes. Toutes ces méthodes sous-jacentes comportent désormais également des erreurs capturées (involontairement) par la capture sus-jacente.

Si vous avez besoin d’attraper une erreur, faites-le dans une fasion étroite et contrôlée. 

2
Martin Nielsen

Si vous codez de manière défensive et que vous pouvez résoudre un problème, il ne s'agit pas d'un nom Java Error. Si un tel problème est peu probable, créez une sous-classe de Exception et lancez-la. Si un tel problème est probable, il ne devrait même pas lancer un Exception; mais, devrait faire partie du flux de code normal.

try {
  if (config.hasCustomDLL()) {
    System.load(config.getCustomDLL());
  } else {
    System.loadLibrary(Config.DEFAULT_DLL);
  }
} catch (UnstatisfiedLinkError e) {
  System.out.println("Error loading DLL: " + e);
}

Errors sont destinés à des échecs vraiment graves, pas des "échecs" récupérables qui ne sont même pas des échecs s'il existe une solution de contournement appropriée. Ne surchargez pas le système conçu pour gérer les échecs avec ce qui revient à une capacité à configurer le système de plusieurs manières.

0
Edwin Buck

loadLibrary appelle findLibrary (), ce qui serait utile mais protégé, votre meilleur pari est d'écrire votre propre classe avec ClassLoader. Le chargeur de classes a une méthode protégée appelée findLibrary () qui renverra le chemin d'accès à une bibliothèque ou null si elle n'existe pas. De cette façon, vous pouvez simplement vérifier la valeur null au lieu de détecter les erreurs. Je ne suis pas sûr que ce soit réellement "meilleur", mais cela vous évitera d'avoir à essayer.

0
Jordon Biondo