-Xlint-Optionen von javac

Der von Oracle (und früher von Sun) bereitgestellte Java-Programmiersprachen-Compiler (javac) verfügt über mehrere nicht standardmäßige Optionen, die häufig nützlich sind. Eine der nützlichsten Optionen sind nicht standardmäßige Optionen, mit denen während der Kompilierung auftretende Warnungen ausgedruckt werden. Diese Optionen sind Gegenstand dieses Beitrags.

Der Abschnitt mit den Javac-Seiten zu nicht standardmäßigen Optionen listet kurze Details zu jeder dieser Optionen auf. Das Folgende ist das relevante Snippet von dieser Seite.

Eine Liste dieser Optionen ist auch über die Befehlszeile (vorausgesetzt, das Java SDK ist installiert) mit dem folgenden Befehl verfügbar: javac -help -X. Dies ist kürzer als das oben gezeigte Manpage- / Webseitenbeispiel und wird als nächstes gezeigt.

Wie die vorhergehende Momentaufnahme aus laufen javac -help -Xdie zehn spezifischen Bedingungen für die Xlint Warnungen vorhanden sind (in alphabetischer Reihenfolge) anzeigt,: cast, deprecation, divzero, empty, fallthrough, finally, overrides, path, serial, und unchecked. Ich schaue mir diese kurz an und stelle ein Code-Snippet bereit, das dazu führt, dass diese Warnung auftritt, wenn Xlint eingeschaltet wird. Beachten Sie, dass sowohl die Manpage für Javac als auch die Java SE 6-Javac-Seite nur die Hälfte dieser Xlint-Optionen auflisten (die Dokumentation ist anscheinend nicht so aktuell wie die Verwendung / Hilfe von Javac). Es gibt einen nützlichen NetBeans-Wiki-Eintrag, der alle zehn Optionen zusammenfasst.

Mit dem Javac-Compiler können alle oder keine Xlint-Warnungen aktiviert werden. Wenn Xlint in der Option -Xlint: none überhaupt nicht angegeben ist, werden die meisten Warnungen nicht angezeigt. Interessanterweise enthält die Ausgabe eine Warnung zu veralteten und nicht aktivierten Warnungen und empfiehlt, javac mit aktiviertem -Xlint auszuführen, um die Details zu diesen beiden Arten von Warnungen anzuzeigen.

Vor dem Ende dieses Beitrags werde ich Java-Code demonstrieren, der zu insgesamt 13 gemeldeten Xlint-Warnungen führt, die alle zehn oben beschriebenen Optionen abdecken. Ohne Angabe von Xlint erfolgt die Ausgabe jedoch wie im nächsten Screenshot gezeigt.

Wie das obige Bild zeigt, ist das Ergebnis dasselbe, unabhängig davon, ob Xlint überhaupt nicht oder explizit mit "none" angegeben ist: Die meisten Warnungen werden nicht angezeigt, es gibt jedoch einfache Verweise auf die Verwerfungen und ungeprüfte Warnungen mit Empfehlungen um javac mit -Xlint: deprecation und -Xlint: auszuführen, die für weitere Details deaktiviert sind. Wenn Sie javac mit -Xlint: all oder -Xlint ohne andere Optionen ausführen, werden alle Warnungen angezeigt, und es werden die Details zu veralteten, nicht aktivierten und allen anderen anwendbaren Xlint-fähigen Warnungen angezeigt. Dies wird angezeigt, nachdem Sie den Quellcode und jede Xlint-Warnung einzeln durchgesehen haben.

-Xlint: Besetzung

Mit dieser Option kann der Compiler den Entwickler warnen, dass eine redundante Umwandlung vorgenommen wird. Hier ist ein Code-Snippet, das markiert wird, wenn javac beim Kompilieren der Quelle -Xlint, -Xlint: all oder -Xlint: cast zur Verfügung gestellt wird.

/** * 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()); } } 

Im obigen Code ist es nicht erforderlich, das person-Objekt in der for-Schleife in Person und -Xlint umzuwandeln: cast warnt vor dieser unnötigen und redundanten Umwandlung mit einer Meldung wie:

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

-Xlint: Verfall

Wie oben erläutert, wurde die Xlint-Verfallswarnung offensichtlich als wichtig genug angesehen, um zu rechtfertigen, dass sie auch dann angekündigt wird, wenn Xlint nicht explizit ausgeführt wird. Diese Warnung tritt auf, wenn eine veraltete Methode aufgerufen wird. Das folgende Codebeispiel zeigt einen solchen Fall.

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

Sie können nicht ohne den Quellcode für die Person-Klasse (von der "fred" eine Instanz ist) sagen, aber diese getName () -Methode ist in Person veraltet. Die folgende Ausgabe von javac mit -Xlint, -Xlint: all oder -Xlint: veraltet bestätigt dies (oder weist darauf hin, wenn der Entwickler es verpasst hat).

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

Die Option divzero Xlint gibt an, wann die integrale Division durch eine wörtliche Null geteilt wird. Ein Codebeispiel, das dies demonstriert, wird als Nächstes gezeigt:

/** * 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; } 

Die Ausgabe von javac beim Kompilieren wird nun angezeigt.

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

Als ich absichtlich versuchte, diese Warnung zu erzwingen, schien sie nur für einen fest codierten (wörtlichen) Nullteiler zu funktionieren. Außerdem wird keine doppelte Division markiert, da Infinity in diesem Fall als gültige Antwort zurückgegeben werden kann, ohne eine Ausnahme auszulösen.

-Xlint: leer

Der Zweck von -Xlint:emptybesteht darin, den Entwickler darüber zu informieren, dass ifder Code eine "leere" Bedingung enthält. Nach meinen Tests scheint dies nur für den Fall des leeren "if" -Blocks zu gelten. NetBeans bietet "Hinweise" (diese gelb unterstrichenen Warnungen, die auch am rechten Rand des Quellcode-Editors markiert sind) für verschiedene Arten von leeren Anweisungen, -Xlint:emptyscheint jedoch nur die leeren "if" -Anweisungen zu kennzeichnen . Ich habe die anderen, die NetBeans zusammen mit den einen -Xlint:emptyFlags kennzeichnet, in das nächste Quellcodebeispiel aufgenommen.

/** * 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.");;;; } 

Der obige Code enthält eine problematische Platzierung von Semikolons, die mit ziemlicher Sicherheit nicht den Wünschen des Entwicklers entsprechen. Dieser Code wird kompiliert, aber der Entwickler dieser verdächtigen Situationen gewarnt , wenn -Xlint, -Xlint:alloder -Xlint:emptymit javac verwendet. Als nächstes werden die Warnmeldungen angezeigt, die in der ansonsten erfolgreichen Kompilierung gedruckt werden.

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

Nur die leere "if" -Anweisungsklausel ist markiert. Die anderen werden von nicht gemeldet -Xlint:empty.

-Xlint: Durchfall

Eine verlockende, aber kontroverse Annehmlichkeit, die Java bietet, ist die Möglichkeit, allgemeine Ausdrücke in einer switchAnweisung zu "durchfallen" , um dieselbe Logik auf mehrere Integralwerte mit einem Codeteil anzuwenden. Wenn alle Integralwerte mit der gemeinsam genutzten Funktionalität leer sind, mit Ausnahme des letzten Werts, der die Funktionalität tatsächlich ausführt und a bereitstellt break, -Xlint:fallthroughwird der nicht aktiviert. Wenn jedoch einige der caseAusdrücke zusätzlich zur allgemeinen Durchfalllogik eine eigene Logik ausführen, wird diese Warnung ausgegeben. Ein Beispiel, das dies demonstriert, wird als nächstes gezeigt.

/** * 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."); } } 

Das obige Codebeispiel zeigt absichtlich beide Fälle (Wortspiel beabsichtigt) des Schalters / Falls, die dank zu einer Warnmeldung führen und nicht -Xlint:fallthrough. Die Ausgabe mit nur einer Warnung wird als nächstes angezeigt.

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

Das case, was markiert wurde, war das ROT casenach dem GRÜN case, das eine eigene Logik ausführte, bevor es zur ROTEN Logik durchfiel.

-Xlint: endlich

Mehr als eine Person hat gewarnt: "Kehren Sie nicht in einer finally-Klausel zurück." Tatsächlich befindet sich "Javas Rückkehr nicht immer" in der Java Hall of Shame. Ein Java - Entwickler kann mit dieser schändlichen Situation gewarnt werden -Xlint, -Xlint:alloder -Xlint:finally. Als nächstes wird ein Quellcode gezeigt, der zeigt, wie diese Warnung generiert werden kann.

/** * 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; } } 

Das Obige ist fehlerhaft und wahrscheinlich nicht das, was der Entwickler beabsichtigt hat. Die entsprechende Warnung, die Javac bereitstellt, wenn Xlint aktiviert ist, wird als Nächstes angezeigt.

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

-Xlint: überschreibt