javac's -Xlint Options

Kompilator języka programowania Java (javac) dostarczany przez firmę Oracle (a wcześniej przez firmę Sun) ma kilka niestandardowych opcji, które są często przydatne. Jedną z najbardziej użytecznych jest zestaw niestandardowych opcji, które wyświetlają ostrzeżenia napotkane podczas kompilacji. Ten zestaw opcji jest przedmiotem tego postu.

Sekcja strony javac zawierająca listę opcji niestandardowych i zawiera krótkie szczegółowe informacje o każdej z nich. Poniżej znajduje się odpowiedni fragment z tej strony.

Lista tych opcji jest również dostępna z wiersza poleceń (zakładając, że jest zainstalowany pakiet Java SDK) za pomocą polecenia: javac -help -X. Jest to krótsze niż przykład strony podręcznika / strony internetowej pokazany powyżej i jest pokazany obok.

Ponieważ poprzednie migawka uruchamianie javac -help -Xwskazuje dziesięć warunków specyficznych dla których nie ostrzeżenia Xlint (w kolejności alfabetycznej): cast, deprecation, divzero, empty, fallthrough, finally, overrides, path, serial, i unchecked. Pokrótce przyjrzę się każdemu z nich i podaję fragment kodu, który prowadzi do tych ostrzeżeń, które pojawiają się, gdy Xlint jest włączony. Zauważ, że strona podręcznika javac i strona Java SE 6 javac zawierają tylko połowę tych opcji Xlint (dokumentacja najwyraźniej nie jest tak aktualna jak użycie / pomoc javaca). Istnieje przydatny wpis NetBeans Wiki, który podsumowuje wszystkie dziesięć opcji.

Kompilator javac pozwala na włączenie wszystkich ostrzeżeń Xlint lub żadnego z nich. Jeśli Xlint nie jest w ogóle określony, opcja -Xlint: none jest wyraźnie określona, ​​zachowanie polega na tym, aby nie pokazywać większości ostrzeżeń. Co ciekawe, wynik zawiera ostrzeżenie o wycofaniu i niezaznaczonych ostrzeżeniach i zaleca uruchomienie javac z włączoną opcją -Xlint, aby zobaczyć szczegóły tych dwóch typów ostrzeżeń.

Przed końcem tego posta pokażę kod Javy, który prowadzi do 13 łącznie zgłoszonych ostrzeżeń Xlint, obejmujących wszystkie dziesięć opcji omówionych powyżej. Jednak bez określenia Xlint dane wyjściowe są takie, jak pokazano na następnej migawce ekranu.

Jak widać na powyższym obrazku, niezależnie od tego, czy Xlint nie jest w ogóle określony, czy jest wyraźnie określony jako „none”, wynik jest taki sam: większość ostrzeżeń nie jest pokazana, ale istnieją proste odniesienia do wycofania i niezaznaczonych ostrzeżeń z zaleceniami aby uruchomić javac z -Xlint: deprecation i -Xlint: niezaznaczone odpowiednio dla dodatkowych szczegółów. Uruchomienie javac z -Xlint: all lub -Xlint bez innych opcji spowoduje wyświetlenie wszystkich ostrzeżeń i wyświetlenie szczegółów dotyczących przestarzałych, niezaznaczonych i wszystkich innych odpowiednich ostrzeżeń obsługujących Xlint. Zostanie to pokazane po przejrzeniu kodu źródłowego i każdego ostrzeżenia Xlint indywidualnie.

-Xlint: obsada

Tej opcji można użyć, aby kompilator ostrzegał programistę o wykonywaniu nadmiarowego rzutowania. Oto fragment kodu, który zostałby oflagowany, gdyby -Xlint, -Xlint: all lub -Xlint: cast został dostarczony do javac podczas kompilowania źródła.

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

W powyższym kodzie nie ma potrzeby rzutowania obiektu osoby wewnątrz pętli for na osobę i -Xlint: cast będzie ostrzegał o tym niepotrzebnym i redundantnym rzutowaniu komunikatem o treści w rodzaju:

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

-Xlint: przestarzałe

Jak omówiono powyżej, ostrzeżenie o wycofaniu Xlint zostało najwyraźniej uznane za wystarczająco ważne, aby uzasadnić reklamowanie go nawet wtedy, gdy Xlint nie jest jawnie uruchamiany. To ostrzeżenie pojawia się, gdy zostanie wywołana przestarzała metoda. Poniższy przykład kodu demonstruje taki przypadek.

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

Nie można stwierdzić bez kodu źródłowego klasy Person (której instancją jest „fred”), ale ta metoda getName () jest przestarzała w Person. Poniższe dane wyjściowe uruchomienia javaca z opcją -Xlint, -Xlint: all lub -Xlint: deprecation potwierdza to (lub zwraca uwagę, jeśli programista to przegapił).

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

Opcja divzero Xlint wskazuje, kiedy dzielenie całkowe dzieli się przez dosłowne zero. Przykład kodu, który to zademonstruje, jest pokazany poniżej:

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

Wyświetlane są teraz dane wyjściowe z javaca po kompilacji powyższego.

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

Kiedy celowo próbowałem wymusić to ostrzeżenie, wydawało się, że działa ono tylko dla zakodowanego (dosłownego) dzielnika zera. Ponadto nie oznacza podwójnego dzielenia, ponieważ w takim przypadku Infinity może zostać zwrócone jako poprawna odpowiedź bez zgłaszania wyjątku.

-Xlint: pusty

Celem -Xlint:emptyjest powiadomienie dewelopera, że ifw kodzie znajduje się „pusty” warunek. Z moich testów wynika, że ​​dotyczy to tylko przypadku pustego bloku „if”. NetBeans dostarcza „podpowiedzi” (te żółte, podkreślone ostrzeżenia, które są również zaznaczone na prawym marginesie edytora kodu źródłowego) dla kilku typów pustych instrukcji, ale -Xlint:emptywydaje się , że oflagowuje tylko puste instrukcje „if”. Dodałem inne, które NetBeans flaguje wraz z -Xlint:emptyflagą one w następnym przykładzie kodu źródłowego.

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

Powyższy kod jest wypełniony problematycznymi średnikami, które prawie na pewno nie są tym, czego chciał programista. Ten kod kompiluje, ale deweloper ostrzegł tych podejrzanych sytuacjach, gdy -Xlint, -Xlint:alllub -Xlint:emptyjest używany z javac. Komunikaty ostrzegawcze, które są drukowane podczas kompilacji, która w przeciwnym razie zakończyła się powodzeniem, są wyświetlane jako następne.

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

Oznaczana jest tylko pusta klauzula instrukcji „if”; inne nie są zgłaszane przez -Xlint:empty.

-Xlint: fallthrough

Kusząca, ale kontrowersyjna wygoda, jaką zapewnia Java, to możliwość „przełamania” typowych wyrażeń w switchinstrukcji w celu zastosowania tej samej logiki do wielu wartości całkowitych za pomocą jednego fragmentu kodu. Jeśli wszystkie wartości całkowite ze współdzieloną funkcjonalnością są puste, z wyjątkiem ostatniej, która faktycznie wykonuje tę funkcjonalność i dostarcza a break, -Xlint:fallthroughnie zostanie aktywowana. Jeśli jednak niektóre casewyrażenia wykonują własną logikę oprócz zwykłej logiki upadku, generowane jest to ostrzeżenie. Przykłady, które to demonstrują, przedstawiono poniżej.

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

Powyższy przykład kodu celowo pokazuje oba przypadki (gra słów zamierzona) przełącznika / przypadku, które doprowadzą i nie doprowadzą do komunikatu ostrzegawczego dzięki -Xlint:fallthrough. Wyjście z tylko jednym ostrzeżeniem jest wyświetlane jako następne.

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

To, caseco zostało oflagowane, to RED casepodążający za ZIELONYM, casektóry wykonał swoją własną logikę, zanim przeszedł do logiki RED.

-Xlint: wreszcie

Więcej niż jedna osoba ostrzegła: „Nie wracaj w klauzuli ostatecznej”. W rzeczywistości „Powrót Javy nie zawsze” znajduje się w Java Hall of Shame. Programista Java może zostać ostrzeżony o tym nikczemnym sytuacji za pomocą -Xlint, -Xlint:all, lub -Xlint:finally. Następnie pokazany jest fragment kodu źródłowego pokazujący, jak można wygenerować to ostrzeżenie.

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

Powyższe jest wadliwe i prawdopodobnie nie jest tym, co zamierzał programista. Odpowiednie ostrzeżenie, które javac wyświetla, gdy Xlint jest włączony, jest pokazane jako następne.

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

-Xlint: nadpisuje