Options -Xlint de javac

Le compilateur de langage de programmation Java (javac) fourni par Oracle (et anciennement par Sun) a plusieurs options non standard qui sont souvent utiles. L'un des plus utiles est l'ensemble des options non standard qui affichent les avertissements rencontrés lors de la compilation. Cet ensemble d'options est le sujet de cet article.

La section de la page javac sur les options non standard répertorie et fournit de brefs détails sur chacune de ces options. Voici l'extrait de code pertinent de cette page.

Une liste de ces options est également disponible à partir de la ligne de commande (en supposant que le SDK Java est installé) avec la commande: javac -help -X. Ceci est plus bref que l'exemple de page de manuel / page Web présenté ci-dessus et est illustré ci-dessous.

Comme l'instantané précédent de fonctionnement javac -help -Xindique, les dix conditions spécifiques pour lesquelles les avertissements existent Xlint sont (par ordre alphabétique): cast, deprecation, divzero, empty, fallthrough, finally, overrides, path, serialet unchecked. Je regarde brièvement chacun d'entre eux et je fournis un extrait de code qui conduit à ces avertissements lorsque Xlint est activé. Notez que la page de manuel pour javac et la page Java SE 6 javac ne répertorient que la moitié de ces options Xlint (la documentation n'est apparemment pas aussi à jour que l'utilisation / l'aide de javac). Il existe une entrée utile du Wiki NetBeans qui résume les dix options.

Le compilateur javac permet d'activer tous ou aucun des avertissements Xlint. Si Xlint n'est pas du tout spécifié de l'option -Xlint: none est explicitement spécifié, le comportement est de ne pas afficher la plupart des avertissements. Fait intéressant, la sortie fournit un avertissement concernant la dépréciation et les avertissements non vérifiés et recommande d'exécuter javac avec -Xlint activé pour voir les détails sur ces deux types d'avertissements.

Avant la fin de cet article, je vais démontrer le code Java qui conduit à 13 avertissements Xlint au total rapportés couvrant les dix options décrites ci-dessus. Cependant, sans Xlint spécifié, la sortie est comme indiqué dans l'instantané d'écran suivant.

Comme l'image ci-dessus l'indique, que Xlint ne soit pas spécifié du tout ou soit spécifié explicitement avec "aucun", le résultat est le même: la majorité des avertissements ne sont pas affichés, mais il y a de simples références à la dépréciation et des avertissements non vérifiés avec des recommandations pour exécuter javac avec -Xlint: deprecation et -Xlint: décochés respectivement pour plus de détails. Exécuter javac avec -Xlint: all ou -Xlint sans autre option affichera tous les avertissements et fonctionnerait pour voir les détails concernant les avertissements obsolètes, non cochés et tous les autres avertissements activés par Xlint applicables. Cela sera affiché après avoir parcouru le code source et chaque avertissement Xlint individuellement.

-Xlint: fonte

Cette option peut être utilisée pour que le compilateur avertisse le développeur qu'une conversion redondante est en cours. Voici un extrait de code qui serait signalé si -Xlint, -Xlint: all ou -Xlint: cast était fourni à javac lors de la compilation des sources.

/** * Demonstrates -Xlint:cast warning of a redundant cast. */ private static void demonstrateCastWarning() { final Set people = new HashSet(); people.add(fred); people.add(wilma); people.add(barney); for (final Person person : people) { // Redundant cast because generic type explicitly is Person out.println("Person: " + ((Person) person).getFullName()); } } 

Dans le code ci-dessus, il n'est pas nécessaire de convertir l'objet personne à l'intérieur de la boucle for en Person et -Xlint: cast avertira de ce cast inutile et redondant avec un message indiquant quelque chose comme:

src\dustin\examples\Main.java:37: warning: [cast] redundant cast to dustin.examples.Person out.println("Person: " + ((Person) person).getFullName()); ^ 

-Xlint: dépréciation

Comme indiqué ci-dessus, l'avertissement de dépréciation de Xlint a été évidemment jugé suffisamment important pour justifier sa publication même lorsque Xlint n'est pas explicitement exécuté. Cet avertissement se produit lorsqu'une méthode obsolète est appelée. L'exemple de code suivant illustre un tel cas.

/** * Cause -Xlint:deprecation to print warning about use of deprecated method. */ private static void demonstrateDeprecationWarning() { out.println("Fred's full name is " + fred.getName()); } 

Vous ne pouvez pas le dire sans le code source de la classe Person (dont "fred" est une instance), mais cette méthode getName () est obsolète dans Person. La sortie suivante de l'exécution de javac avec -Xlint, -Xlint: all ou -Xlint: deprecation le confirme (ou le souligne si le développeur l'a manqué).

src\dustin\examples\Main.java:47: warning: [deprecation] getName() in dustin.examples.Person has been deprecated out.println("Fred's full name is " + fred.getName()); ^ 

-Xlint: divzero

L'option divzero Xlint indique quand la division intégrale divise par un zéro littéral. Un exemple de code qui démontrera cela est montré ci-dessous:

/** * Demonstrate -Xlint:divzero in action by dividing an int by a literal zero. */ private static void demonstrateDivideByZeroWarning() { out.println("Two divided by zero is " + divideIntegerByZeroForLongQuotient(2)); } /** * Divide the provided divisor into the provided dividend and return the * resulting quotient. No checks are made to ensure that divisor is not zero. * * @param dividend Integer to be divided. * @return Quotient of division of dividend by literal zero. */ private static long divideIntegerByZeroForLongQuotient(final int dividend) { // Hard-coded divisor of zero will lead to warning. Had the divisor been // passed in as a parameter with a zero value, this would not lead to // that warning. return dividend / 0; } 

La sortie de javac lorsque ce qui précède est compilé est maintenant affichée.

src\dustin\examples\Main.java:231: warning: [divzero] division by zero return dividend / 0; ^ 

Lorsque j'ai intentionnellement essayé de forcer cet avertissement, il semblait ne fonctionner que pour un diviseur zéro codé en dur (littéral). En outre, il ne marque pas la double division car Infinity peut être renvoyé comme une réponse valide dans ce cas sans lever d'exception.

-Xlint: vide

Le but de -Xlint:emptyest d'avertir le développeur qu'un ifconditionnel «vide» est dans le code. D'après mes tests, cela ne semble s'appliquer que pour le cas du bloc "si" vide. NetBeans fournit des «conseils» (ces avertissements soulignés en jaune qui sont également marqués dans la marge droite de l'éditeur de code source) pour plusieurs types d'instructions vides, mais -Xlint:emptysemble ne marquer que les instructions «if» vides. J'ai inclus les autres indicateurs que NetBeans marque avec l'un des -Xlint:emptyindicateurs dans l'exemple de code source suivant.

/** * This method demonstrates how javac's -Xlint:empty works. Note that javac's * -Xlint:empty will only flag the empty statement involved in the "if" block, * but does not flag the empty statements associated with the do-while loop, * the while loop, the for loop, or the if-else. NetBeans does flag these if * the appropriate "Hints" are turned on. */ private static void demonstrateEmptyWarning() { int[] integers = {1, 2, 3, 4, 5}; if (integers.length != 5); out.println("Not five?"); if (integers.length == 5) out.println("Five!"); else; out.println("Not Five!"); do; while (integers.length > 0); for (int integer : integers); out.println("Another integer found!"); int counter = 0; while (counter < 5); out.println("Extra semicolons.");;;; } 

Le code ci-dessus est rempli de placement problématique de points-virgules qui ne sont certainement pas ce que le développeur voulait. Ce code compilera, mais le développeur est mis en garde contre ces situations suspectes si -Xlint, -Xlint:allou -Xlint:emptyest utilisé avec javac. Les messages d'avertissement qui sont imprimés dans la compilation par ailleurs réussie sont affichés ci-dessous.

src\dustin\examples\Main.java:197: warning: [empty] empty statement after if if (integers.length != 5); ^ 

Seule la clause d'instruction "if" vide est marquée; les autres ne sont pas signalés par -Xlint:empty.

-Xlint: chute

Une commodité tentante mais controversée fournie par Java est la possibilité de «passer» les expressions courantes dans une switchinstruction pour appliquer la même logique à plusieurs valeurs intégrales avec un seul morceau de code. Si toutes les valeurs intégrales avec la fonctionnalité partagée sont vides à l'exception de la dernière qui exécute réellement la fonctionnalité et fournit un break, le -Xlint:fallthroughne sera pas activé. Toutefois, si certaines des caseexpressions exécutent leur propre logique en plus de la logique de secours commune, cet avertissement est généré. Un exemple illustrant cela est présenté ci-après.

/** * Cause -Xlint:fallthrough to print warning about use of switch/case * fallthrough. */ private static void demonstrateFallthroughWarning() { out.print("Wilma's favorite color is "); out.print(wilma.getFavoriteColor() + ", which is "); // check to see if 'artistic' primary color // NOTE: This one will not lead to -Xlint:fallthrough flagging a warning // because no functionality is included in any of the case statements // that don't have their own break. switch (wilma.getFavoriteColor()) { case BLUE: case YELLOW: case RED: out.print("a primary color for artistic endeavors"); break; case BLACK: case BROWN: case CORAL: case EGGSHELL: case GREEN: case MAUVE: case ORANGE: case PINK: case PURPLE: case TAN: case WHITE: default: out.print("NOT a primary artistic color"); } out.print(" and is "); // check to see if 'additive' primary color // NOTE: This switch WILL lead to -Xlint:fallthrough emitting a warning // because there is some functionality being performed in a case // expression that does not have its own break statement. switch (wilma.getFavoriteColor()) { case BLUE: case GREEN: out.println("(it's not easy being green!) "); case RED: out.println("a primary color for additive endeavors."); break; case BLACK: case BROWN: case CORAL: case EGGSHELL: case MAUVE: case ORANGE: case PINK: case PURPLE: case TAN: case YELLOW: case WHITE: default: out.println("NOT a primary additive color."); } } 

L'exemple de code ci-dessus montre intentionnellement les deux cas (jeu de mots) du commutateur / cas qui conduiront et ne mèneront pas à un message d'avertissement grâce à -Xlint:fallthrough. La sortie, avec un seul avertissement, est affichée ensuite.

src\dustin\examples\Main.java:95: warning: [fallthrough] possible fall-through into case case RED: ^ 

Le casequi a été signalé était le ROUGE casesuivant le VERT casequi a fait sa propre logique avant de passer à la logique ROUGE.

-Xlint: enfin

Plus d'une personne a averti: «Ne revenez pas dans une clause finale». En fait, «le retour de Java n'est pas toujours» se trouve dans le Java Hall of Shame. Un développeur Java peut être mis en garde contre cette situation néfaste à l'aide -Xlint, -Xlint:allou -Xlint:finally. Un morceau de code source montrant comment cet avertissement peut être généré est affiché ci-après.

/** * Demonstrate -Xlint:finally generating warning message when a {@code finally} * block cannot end normally. */ private static void demonstrateFinallyWarning() { try { final double quotient = divideIntegersForDoubleQuotient(10, 0); out.println("The quotient is " + quotient); } catch (RuntimeException uncheckedException) { out.println("Caught the exception: " + uncheckedException.toString()); } } /** * Divide the provided divisor into the provided dividend and return the * resulting quotient. No checks are made to ensure that divisor is not zero. * * @param dividend Integer to be divided. * @param divisor Integer by which dividend will be divided. * @return Quotient of division of dividend by divisor. */ private static double divideIntegersForDoubleQuotient(final int dividend, final int divisor) { double quotient = 0.0; try { if (divisor == 0) { throw new ArithmeticException( "Division by zero not allowed: cannot perform " + dividend + "/" + divisor); } // This would not have led to Xlint:divzero warning if we got here // with a literal zero divisor because Infinity would have simply been // returned rather than implicit throwing of ArithmeticException. quotient = (double) dividend / divisor; } finally { return quotient; } } 

Ce qui précède est imparfait et n'est probablement pas ce que le développeur avait prévu. L'avertissement approprié que javac fournit lorsque Xlint est activé est affiché ensuite.

src\dustin\examples\Main.java:159: warning: [finally] finally clause cannot complete normally } ^ 

-Xlint: remplace