17

Wir haben ein Java-Projekt. Wir aktivieren -Xlint (aktivieren Warnungen) und -Werror (behandeln Warnung als Fehler) Flags für javac, um sicherzustellen, dass unser Code warnungsfrei ist. Vor kurzem haben wir beschlossen, eine Klasse abzulehnen. Das Problem besteht in einigen Fällen darin, dass @SuppressWarnings("deprecation") die Verwarnungswarnung überhaupt nicht unterdrückt, was zu einem Buildfehler führt. Im Folgenden finden Sie eine Liste der Anwendungsfälle, die ich lief:Wie vermeidet man Abneigungswarnungen, wenn @SuppressWarnings ("deprecation") nicht funktioniert?

  1. Importiert in anderen nicht veralteten Klassen.
  2. Importiert in andere veraltete Klassen.
  3. Elternklasse.
  4. Typ Parameter. Zum Beispiel

    @SuppressWarnings("deprecation") 
    public class Foo extends Bar<DeprecatedClass> 
    { ... } 
    

    Dies hat jedoch eine keine Warnung auch ohne Unterdrückungs:

    @Deprecated 
    public class DeprecatedClass extends Bar<DeprecatedClass> 
    { ... } 
    

AFAIK gibt es keine Syntax für Kommentierung Importe, also für den Fall 1 und 2 unserer Lösung ist, Import * oder Import vermeiden. Für Fall 3 und 4 unterdrücken sowohl Java 6 als auch 7 die Warnung nicht. Java 8 wird es korrekt unterdrücken (vielleicht ist ein Fehler behoben). Bisher keine Lösung dafür.

Leider müssen wir Java 6, 7 und 8 an dieser Stelle unterstützen. Gibt es einen Weg, mit dem Problem umzugehen? Es ist eine Blockade für unsere Java-API-Entwicklung.

NACHTRAG

Viele Leute fragen, warum wir immer noch die veraltete Klasse in unserer eigenen Code-Basis verwenden. Der Grund ist, dass das Projekt eine Bibliothek ist, die viele verschiedene Kunden unterstützt. Bei der Einführung einer neuen Ersetzungs-API müssen wir zuerst unsere alte API deaktivieren, sie in unserer Codebasis behalten, auf die Migration aller Clients warten und sie dann entfernen. Es gibt drei gängige Anwendungsfälle:

  • Wir verbitten Klasse Foo und Bar, wo FooBar erstreckt. Dies ist der Fall 2 und 3 in meiner Frage.
  • Wir verwerfen Klasse Foo und Bar, wobei Foo erweitert Collection<Bar>. Dies ist der Fall 2 und 4.
  • Wir müssen alle Test-Code für Klasse Foo und Bar halten. Der Testcode importiert diese Klassen. Dies ist der Fall 1.

Warum den Test halten? Vergessen Sie nicht, dass, wenn ein schwerwiegender Fehler (z. B. Speicherverlust, Sicherheitsproblem) entdeckt wird und die Clients nicht problemlos auf die neue Version migrieren können, wir weiterhin eine Fehlerbehebung für die alte API bereitstellen müssen. Und alle Änderungen müssen getestet werden.

Ich denke, dass unsere Situation in der Software-Bibliotheksentwicklung und API-Entwicklung relativ häufig vorkommen sollte. Überraschenderweise brauchte Java so lange (bis Java 8), um den Fehler zu beheben.

+2

Es gibt wahrscheinlich nicht viele Möglichkeiten. Sie könnten Ihren Build-Prozess so ändern, dass kein "-Werror" außer target == 8 auftritt, oder veraltete Warnungen ausschließen, da dies in 6 und 7 zu brechen scheint. Oder Sie führen keine Standard-Abwertung durch (imo eine schlechte Alternative): Überspringen deprecation und die schlechte Klasse sofort entfernen, „deprecate“ durch eine Notiz aus, die im Internet/javadoc setzen, oder in dem Fall, dass jede Klasse, die es als Typ-Parameter verwendet, auch wenn es bei der veralteten Klasse bleiben würde würde auch verbitten Werke verschwinden. Auch http://stackoverflow.com/a/20909204/995891 in Bezug auf 1) und 2) – zapl

+0

Ich denke deprecate nicht Fall 3 und setzen '@ deprecated' in Javadoc könnte der letzte Ausweg sein, wenn kein besserer Ansatz besteht. –

+0

Da Sie verweisen sie Typ als nicht-Klasse, können Sie erweitern gattungsgemäße Verwendung und gegossen zu 'DeprecatedClass' später, mit einer Warnung Unterdrückung um die Besetzung? – CharlieS

Antwort

7

Es tut mir leid zu sagen, dass ich keine Lösung für das Problem habe, mit dem Sie konfrontiert sind, obwohl es, wie Sie gesehen haben, einige Fortschritte gegeben hat. Wir haben versucht, alle Java-Kompilierungswarnungen im JDK selbst zu entfernen, und dies war ein langer, schwieriger Prozess. Während JDK 8 Entwicklung im Jahr 2011 half ich kick off the warnings cleanup effort und ich später co-presented a JavaOne talk (slides and audio) zum Thema.

Vor kurzem hat mein Kollege Joe Darcy die Warnungen Bereinigung Arbeit fortgesetzt und hat sich durch die verschiedenen Kategorien Warnungen und hat finally reached deprecation warnings. Wie Sie bereits angemerkt haben, gab es einige Fehler in der Compiler-Behandlung der Unterdrückung von veralteten Warnungen, wie JDK-6480588, die in JDK 8 behoben wurde. Leider ist es in JDK 8 immer noch nicht möglich, Warnungen beim Import von veralteten Elementen zu unterdrücken. Dieser Bug, JDK-8032211, wurde vor kurzem in unserer Entwicklungslinie JDK 9 behoben. In der Tat stimmen wir immer noch die Handhabung der @Deprecated Annotation ab. Beispiel: Der Fehler JDK-6481080 verdeutlicht, dass der Versuch, @Deprecated in einer package-info.java-Datei zu verwenden, das Paket nicht veraltet; Dieser Bug wurde erst letzte Woche behoben. Und es gibt more work to be done, aber es ist an dieser Stelle etwas spekulativ.

Das JDK sieht sich ähnlichen Problemen gegenüber, da wir veraltete APIs für Clients beibehalten müssen, die sie noch verwenden. Da wir solche APIs jedoch intern verwenden und implementieren, müssen wir viele Verwarnungswarnungen unterdrücken. Zum jetzigen Zeitpunkt konnten wir in unserer Development Line JDK 9 immer noch nicht in der Lage sein, das System ohne Verwarnungswarnungen zu kompilieren. Als Ergebnis sind die javac Optionen für Flusen Warnungen vor:

-Xlint:all,-deprecation 

Sie werden wahrscheinlich auch müssen deprecation Warnungen in Ihrer Zusammenstellung deaktivieren, vor allem, wenn Sie immer noch auf JDK bauen 6. Ich sehe nicht ein Um es herum an dieser Stelle.

Ein letzter Hinweis auf eine Ihrer deprecation Fälle:

@Deprecated 
public class DeprecatedClass extends Bar<DeprecatedClass> { ... } 

Dieses Problem tritt nicht ein deprecation Warnung, noch sollte es.Die Java Language Specification, section 9.6.4.6 gibt an, dass keine Verwarnungswarnungen ausgegeben werden, wenn sich die Verwendung einer veralteten Entität innerhalb einer Entität befindet, die selbst nicht weiter unterstützt wird.

+0

Danke für die Klärung und den Austausch der JDK-Entwicklung. –

+0

Die letzte Anmerkung ist interessant, weil ich schwöre, ich hatte zu @SuppressWarnings („deprecated“) auf Methoden hinzufügen, die zuvor schon @deprecated wurden ... – Trejkaz

+0

@Trejkaz Bitte senden Sie ein Beispiel, wenn Sie einen finden. –

-3

Wenn Sie die Klasse nicht mehr verwenden, möchten Sie normalerweise nicht, dass sie in späteren Versionen verwendet wird. Außerdem sollte Ihre Codebase auch die veraltete Klasse nicht mehr verwenden. Es sieht komisch aus, wenn Sie sagen, dass Sie nicht die MySuperDeprecatedUtil-Klasse verwenden sollen, sondern sie weiterhin in Ihrer Codebasis verwenden.

Wenn Sie Ihre MySuperDeprecatedUtil-Klasse in einer anderen Klasse verwenden müssen, sollten Sie die Klasse als @Deprecated markieren. Jede Klasse, die veralteten Code verwendet, sollte entweder veraltet sein oder Kompilierungswarnungen erzeugen oder entfernt werden oder sollte den veralteten Code nicht mehr verwenden.

Wenn Sie nicht aufhören können, Ihre Klasse zu verwenden - vielleicht ist es zu früh, um es abzulehnen?

In meiner Praxis, wenn ich einige Klasse ablehnen möchte, erstelle ich Ersatzklasse z. MySuperFreshUtil. Schalten Sie alle Klassen mit MySuperDeprecatedUtil auf MySuperFresh um, wobei die Schnittstellen nach Möglichkeit erhalten bleiben (falls dies nicht möglich ist - verwenden Sie FQCN und markieren Sie die Methode als veraltet). Markieren Sie MySuperDeprecatedUtil als @Deprecated und fügen Sie einen Kommentar hinzu, welche Klasse und wie verwendet werden soll. Dann bestätige ich diese Änderungen in der einzelnen Änderungsliste.

+1

Angenommen, Sie haben 10 Implementierungen einer Abstraktion eines Dateiformats, aus Gründen der Abwärtskompatibilität. Leute sollten nur das neueste Format verwenden, also verurteilen Sie die anderen 9. Die Factory, die das richtige Objekt für eine bestimmte Datei erzeugt, muss immer noch Instanzen der anderen 9 erstellen. Sie können die Methode nicht einfach entfernen, weil sie rückwärts brechen würde Kompatibilität. Sie können die Factory-Methode auch nicht verwerfen, da sie beim Lesen der Dateien weiterhin verwendet wird. Nach dieser Logik besteht die einzige Lösung darin, die neun alten Implementierungen aufzuheben, sodass sie nicht mehr veraltet sind. Ich bin mir nicht sicher, ob ich das möchte. – Trejkaz

1

Verwenden Sie -Xmaxwarns, Sie können steuern, wie viele Warnungen vor dem Stoppen.

Oder versuchen Sie, die Anzahl der Warnungen zu sammeln und den Integrationsprozess fehlgeschlagen, nicht kompilieren.

Zum Beispiel: https://issues.apache.org/jira/browse/HADOOP-11252. Jeder Code, der an das Hadoop-Projekt übergeben wird, muss das automatisierte CI übergeben und -1 zur Erhöhung der Anzahl der Warnungen geben.

Verwandte Themen