Java-Standard-Interface-Methoden konkrete Anwendungsfälle

8

Java 9 wird bald kommen und Java-Schnittstellen wie private Methoden werden um weitere Funktionen erweitert. default Methoden in Schnittstellen wurden in Java 8 hinzugefügt, im Wesentlichen um die Verwendung von Lambdas innerhalb von Sammlungen zu unterstützen ohne die Retro-Kompatibilität mit früheren Versionen der Sprache zu brechen.

In Scala sind Methoden innerhalb von trait s sehr nützlich. Scala hat jedoch einen anderen Ansatz zur Behandlung von trait s als Java mit default Methoden. Denken Sie an die Mehrfachvererbungsauflösung oder die Verwendung von trait s als mixin s.

Abgesehen von der obigen Verwendung, welche sind die realen Szenarien, in denen die Verwendung von default Methoden wert ist? Ist in diesen Jahren ein Muster entstanden, das sie benutzt? Welche Probleme kann ich mit dieser Art von Methoden lösen?

    
riccardo.cardin 27.04.2017, 15:01
quelle

5 Antworten

6

Brian Goetz und ich haben einige davon auf unserem JavaOne 2015 Talk, API Design mit Java 8 Lambda und Streams behandelt. Trotz des Titels gibt es am Ende etwas Material über Standardmethoden.

Folien: Ссылка

Video: Ссылка

Ich werde hier zusammenfassen, was wir über Standardmethoden gesagt haben.

Schnittstellenentwicklung

Der primäre Anwendungsfall von Standardmethoden ist die Schnittstellenevolution. Dies ist hauptsächlich die Möglichkeit, Methoden zu Schnittstellen hinzuzufügen, ohne die Rückwärtskompatibilität zu beeinträchtigen. Wie in der Frage erwähnt, wurde dies am häufigsten verwendet, um Methoden hinzuzufügen, die die Konvertierung von Collections in Streams ermöglichen und Lambda-basierte APIs zu Collections hinzufügen.

Es gibt jedoch mehrere andere Anwendungsfälle.

Optionale Methoden

Manchmal sind Schnittstellenmethoden logisch "optional". Ziehen Sie beispielsweise Mutator-Methoden für unveränderbare Sammlungen in Betracht. Natürlich ist eine Implementierung erforderlich, aber normalerweise wird in solchen Fällen eine Ausnahme ausgelöst. Dies kann leicht in einer Standardmethode durchgeführt werden. Implementierungen können die Exception-throwing-Methode erben, wenn sie diese nicht bereitstellen möchten, oder sie können sie überschreiben, wenn sie eine Implementierung bereitstellen möchten. Beispiel: Iterator.remove .

Convenience-Methoden

Manchmal wird eine Methode für die Bequemlichkeit von Anrufern bereitgestellt, und es gibt eine offensichtliche und optimale Implementierung. Diese Implementierung kann mit einer Standardmethode bereitgestellt werden. Es ist legal, dass eine Implementierung den Standard außer Kraft setzt, aber es gibt im Allgemeinen keinen Grund, weshalb Implementierungen sie normalerweise erben werden. Beispiele: Comparator.reversed , Spliterator.getExactSizeIfKnown , Spliterator.hasCharacteristics . Beachten Sie, dass Spliterator in Java 8 eingeführt wurde, einschließlich des Standardwerts Methoden, so war dies eindeutig kein Fall von Interface-Evolution.

Einfache Implementierung, die überschrieben werden soll

Eine Standardmethode kann eine einfache, allgemeine Implementierung bereitstellen, die für alle Implementierungen funktioniert, aber das ist wahrscheinlich suboptimal. Dies unterstützt Implementierungen während des anfänglichen Hochfahrens, da sie den Standard erben und für einen korrekten Betrieb sorgen können. Auf lange Sicht werden Implementierungen jedoch wahrscheinlich den Standard überschreiben und eine verbesserte, angepasste Implementierung bereitstellen.

Beispiel: List.sort . Die Standardimplementierung kopiert die Listenelemente in ein temporäres Array, sortiert das Array und kopiert die Elemente zurück in die Liste. Dies ist eine korrekte Implementierung und manchmal kann sie nicht verbessert werden (zB für LinkedList ). ArrayList überschreibt jedoch sort und sortiert das interne Array in-place. Dies vermeidet den Kopieraufwand.

Nun wurde natürlich sort in Java 8 auf List und ArrayList nachgerüstet, so dass die Entwicklung nicht auf diese Weise erfolgte. Aber Sie könnten sich leicht vorstellen, eine neue List -Implementierung zu erstellen. Sie würden wahrscheinlich die Standardimplementierung sort erben, während Sie die Grundlagen ordnungsgemäß implementieren. Später könnten Sie einen benutzerdefinierten Sortieralgorithmus implementieren, der auf die interne Datenorganisation Ihrer neuen Implementierung abgestimmt ist.

    
Stuart Marks 28.04.2017, 19:45
quelle
5
___ answer4367457 ___

Nun, ich habe ein realistisches Szenario, in dem ich sie benutzt habe. Hier ist der Kontext: Ich bekomme ein Ergebnis von google maps api (durch Angabe von Längen- und Breitengrad) in Form eines Array der Ergebnisse, das wie folgt aussieht:

%Vor%

Dieses Ergebnis enthält einige Informationen, die ich brauche, wie zip-code oder locality oder country . Verschiedene Dienste benötigen unterschiedliche Teile dieser Antwort. Das Parsen dieses Arrays ist dasselbe - Sie müssen nur nach verschiedenen Teilen suchen.

Also habe ich das in einer default -Methode in interface :

definiert %Vor%

Jetzt bei der Implementierung der Schnittstelle verwende ich einfach diese Methode.

%Vor%

Diese verwendet wird über abstrakte Klassen erstellt. Ich hätte eine private Methode verwenden können, aber diese Schnittstelle wird von vielen anderen Diensten verwendet.

    
___ answer43687853 ___

Brian Goetz und ich haben einige davon auf unserem JavaOne 2015 Talk, API Design mit Java 8 Lambda und Streams behandelt. Trotz des Titels gibt es am Ende etwas Material über Standardmethoden.

Folien: Ссылка

Video: Ссылка

Ich werde hier zusammenfassen, was wir über Standardmethoden gesagt haben.

Schnittstellenentwicklung

Der primäre Anwendungsfall von Standardmethoden ist die Schnittstellenevolution. Dies ist hauptsächlich die Möglichkeit, Methoden zu Schnittstellen hinzuzufügen, ohne die Rückwärtskompatibilität zu beeinträchtigen. Wie in der Frage erwähnt, wurde dies am häufigsten verwendet, um Methoden hinzuzufügen, die die Konvertierung von Collections in Streams ermöglichen und Lambda-basierte APIs zu Collections hinzufügen.

Es gibt jedoch mehrere andere Anwendungsfälle.

Optionale Methoden

Manchmal sind Schnittstellenmethoden logisch "optional". Ziehen Sie beispielsweise Mutator-Methoden für unveränderbare Sammlungen in Betracht. Natürlich ist eine Implementierung erforderlich, aber normalerweise wird in solchen Fällen eine Ausnahme ausgelöst. Dies kann leicht in einer Standardmethode durchgeführt werden. Implementierungen können die Exception-throwing-Methode erben, wenn sie diese nicht bereitstellen möchten, oder sie können sie überschreiben, wenn sie eine Implementierung bereitstellen möchten. Beispiel: %code% .

Convenience-Methoden

Manchmal wird eine Methode für die Bequemlichkeit von Anrufern bereitgestellt, und es gibt eine offensichtliche und optimale Implementierung. Diese Implementierung kann mit einer Standardmethode bereitgestellt werden. Es ist legal, dass eine Implementierung den Standard außer Kraft setzt, aber es gibt im Allgemeinen keinen Grund, weshalb Implementierungen sie normalerweise erben werden. Beispiele: %code% , %code% , %code% . Beachten Sie, dass %code% in Java 8 eingeführt wurde, einschließlich des Standardwerts Methoden, so war dies eindeutig kein Fall von Interface-Evolution.

Einfache Implementierung, die überschrieben werden soll

Eine Standardmethode kann eine einfache, allgemeine Implementierung bereitstellen, die für alle Implementierungen funktioniert, aber das ist wahrscheinlich suboptimal. Dies unterstützt Implementierungen während des anfänglichen Hochfahrens, da sie den Standard erben und für einen korrekten Betrieb sorgen können. Auf lange Sicht werden Implementierungen jedoch wahrscheinlich den Standard überschreiben und eine verbesserte, angepasste Implementierung bereitstellen.

Beispiel: %code% . Die Standardimplementierung kopiert die Listenelemente in ein temporäres Array, sortiert das Array und kopiert die Elemente zurück in die Liste. Dies ist eine korrekte Implementierung und manchmal kann sie nicht verbessert werden (zB für %code% ). %code% überschreibt jedoch %code% und sortiert das interne Array in-place. Dies vermeidet den Kopieraufwand.

Nun wurde natürlich %code% in Java 8 auf %code% und %code% nachgerüstet, so dass die Entwicklung nicht auf diese Weise erfolgte. Aber Sie könnten sich leicht vorstellen, eine neue %code% -Implementierung zu erstellen. Sie würden wahrscheinlich die Standardimplementierung %code% erben, während Sie die Grundlagen ordnungsgemäß implementieren. Später könnten Sie einen benutzerdefinierten Sortieralgorithmus implementieren, der auf die interne Datenorganisation Ihrer neuen Implementierung abgestimmt ist.

    
___ answer43985740 ___

Entfernen des Standardadapters des Listeners mit den Standardmethoden

Manchmal müssen wir die Klasse default %code% für %code% einführen, bei der mehrere Ereignisse ausgelöst werden müssen, aber wir interessieren uns nur für einige der Ereignisse. Beispiel: swing Erstelle jede %code% -Klasse für jede %code% .

Ich fand vor kurzem, dass dies sehr nützlich ist, wenn wir Listener mit Standardmethoden deklarieren, können wir die mittlere Adapterklasse entfernen. zum Beispiel:

%Vor%     
___ qstntxt ___

Java 9 wird bald kommen und Java-Schnittstellen wie private Methoden werden um weitere Funktionen erweitert. %code% Methoden in Schnittstellen wurden in Java 8 hinzugefügt, im Wesentlichen um die Verwendung von Lambdas innerhalb von Sammlungen zu unterstützen ohne die Retro-Kompatibilität mit früheren Versionen der Sprache zu brechen.

In Scala sind Methoden innerhalb von %code% s sehr nützlich. Scala hat jedoch einen anderen Ansatz zur Behandlung von %code% s als Java mit %code% Methoden. Denken Sie an die Mehrfachvererbungsauflösung oder die Verwendung von %code% s als mixin s.

Abgesehen von der obigen Verwendung, welche sind die realen Szenarien, in denen die Verwendung von %code% Methoden wert ist? Ist in diesen Jahren ein Muster entstanden, das sie benutzt? Welche Probleme kann ich mit dieser Art von Methoden lösen?

    
___ answer43663680 ___

Zuerst fällt mir die Verwendung von Standardmethoden zur Unterstützung einiger funktionaler Programmiertechniken ein:

%Vor%

Beispielverwendung:

%Vor%

Sie können ähnliche Bindungsmethoden für die anderen Parameter verwenden, die mit Standardmethoden wie %code% und %code% implementiert werden.

Sie können Standardmethoden verwenden, um die Elternschnittstelle zu dekorieren (wie @holi-java in seiner Antwort erklärt), auch dort gibt es viele Beispiele für das Adaptermuster (currying und binding sind eigentlich Adapter).

Neben der funktionalen Programmierung können Sie Standardmethoden verwenden, um Art , begrenzte Mehrfachvererbung zu unterstützen:

%Vor%

Beispiel:

%Vor%

Vielleicht nicht das beste Beispiel, aber Sie bekommen die Idee ...

Eine andere Verwendung wären Merkmale:

%Vor%

Wenn Sie nun eine Klasse haben, die etwas protokollieren und einige Messwerte melden muss, können Sie Folgendes verwenden:

%Vor%

Auch dies ist nicht die bestmögliche Implementierung, sondern nur Beispielcode, um zu sehen, wie Eigenschaften über Standardmethoden verwendet werden können.

    
___ tag123designpatterns ___ Ein Designmuster ist eine allgemeine wiederverwendbare Lösung für ein häufig auftretendes Problem im Softwaredesign. Verwenden Sie dieses Tag für Fragen, wenn Sie Probleme mit der Implementierung von Entwurfsmustern haben. Bitte verwenden Sie dieses Tag nicht bei Fragen zum Textmustervergleich. ___ tag123java8 ___ Verwenden Sie dieses Tag für spezifische Fragen zu Java 8, Version 8 (interne Nummer 1.8) der Java-Plattform, die am 18. März 2014 veröffentlicht wurde. In den meisten Fällen sollten Sie auch das Java-Tag angeben. ___ tag123java9 ___ Verwenden Sie dieses Tag für spezielle Fragen zu Java 9, Version 9 der Java-Plattform, die am 21. September 2017 veröffentlicht wurde. In den meisten Fällen sollten Sie auch das Java-Tag angeben. ___ tag123defaultmethod ___ Eine Standardmethode ist ein in Java 8 eingeführtes Feature, mit dem eine Schnittstelle einen Methodenkörper deklarieren kann. Klassen, die die Schnittstelle implementieren, müssen keine Standardmethode überschreiben. Verwenden Sie dieses Tag für Fragen zu Standardmethoden. ___ tag123interface ___ Eine Schnittstelle bezieht sich auf den Interaktionspunkt zwischen Komponenten. Schnittstellen sind sowohl auf der Hardware- als auch auf der Softwareebene anwendbar. Im Allgemeinen stellt eine Schnittstelle einen Vertrag offen, ohne die zugrunde liegenden Implementierungsdetails offenzulegen. In objektorientierter Programmierung definieren Schnittstellen abstrakte Typen, die das Verhalten offen legen, aber keine Logik enthalten. Die Implementierung wird durch die Klasse oder den Typ definiert, der die Schnittstelle implementiert. ___ answer43661810 ___

Verziert die Funktionsschnittstelle Verkettung mit Standardmethoden

Ich möchte manchmal @FunctionalInterface verketten, und wir haben bereits in Funktion mit Standardmethoden zum Verketten der Funktion, zB: %code% , %code% , um den Code elegant zu machen. und das wichtigste ist, dass wir die Teilfunktion später wiederverwenden können, zum Beispiel:

%Vor%

Manchmal können wir jedoch das @ FunctionalInterface nicht verketten, da keine Kettenmethoden bereitgestellt wurden. aber ich kann ein anderes schreiben @FunctionalInterface erweitert die ursprünglichen und fügt einige Standardmethoden für die Verkettung hinzu. zum Beispiel:

%Vor%

Das ist die Antwort von mir gestern: Mockito returnFirstArg () zu verwenden . Da %code% keine Kettenmethoden hat, führe ich ein weiteres %code% type %code% ein, um Kettenmethoden bereitzustellen.

AntwortPipeline-Klasse

%Vor%     
___ qstnhdr ___ Java-Standard-Interface-Methoden konkrete Anwendungsfälle ___
Eugene 27.04.2017 20:34
quelle
4

Verziert die Funktionsschnittstelle Verkettung mit Standardmethoden

Ich möchte manchmal @FunctionalInterface verketten, und wir haben bereits in Funktion mit Standardmethoden zum Verketten der Funktion, zB: compose , andThen , um den Code elegant zu machen. und das wichtigste ist, dass wir die Teilfunktion später wiederverwenden können, zum Beispiel:

%Vor%

Manchmal können wir jedoch das @ FunctionalInterface nicht verketten, da keine Kettenmethoden bereitgestellt wurden. aber ich kann ein anderes schreiben @FunctionalInterface erweitert die ursprünglichen und fügt einige Standardmethoden für die Verkettung hinzu. zum Beispiel:

%Vor%

Das ist die Antwort von mir gestern: Mockito returnFirstArg () zu verwenden . Da Answer keine Kettenmethoden hat, führe ich ein weiteres Answer type AnswerPipeline ein, um Kettenmethoden bereitzustellen.

AntwortPipeline-Klasse

%Vor%     
holi-java 27.04.2017 15:19
quelle
4

Zuerst fällt mir die Verwendung von Standardmethoden zur Unterstützung einiger funktionaler Programmiertechniken ein:

%Vor%

Beispielverwendung:

%Vor%

Sie können ähnliche Bindungsmethoden für die anderen Parameter verwenden, die mit Standardmethoden wie bindSecond und bindThird implementiert werden.

Sie können Standardmethoden verwenden, um die Elternschnittstelle zu dekorieren (wie @holi-java in seiner Antwort erklärt), auch dort gibt es viele Beispiele für das Adaptermuster (currying und binding sind eigentlich Adapter).

Neben der funktionalen Programmierung können Sie Standardmethoden verwenden, um Art , begrenzte Mehrfachvererbung zu unterstützen:

%Vor%

Beispiel:

%Vor%

Vielleicht nicht das beste Beispiel, aber Sie bekommen die Idee ...

Eine andere Verwendung wären Merkmale:

%Vor%

Wenn Sie nun eine Klasse haben, die etwas protokollieren und einige Messwerte melden muss, können Sie Folgendes verwenden:

%Vor%

Auch dies ist nicht die bestmögliche Implementierung, sondern nur Beispielcode, um zu sehen, wie Eigenschaften über Standardmethoden verwendet werden können.

    
quelle
3

Entfernen des Standardadapters des Listeners mit den Standardmethoden

Manchmal müssen wir die Klasse default Adapter für java.util.EventListener einführen, bei der mehrere Ereignisse ausgelöst werden müssen, aber wir interessieren uns nur für einige der Ereignisse. Beispiel: swing Erstelle jede *Adapter -Klasse für jede *Listener .

Ich fand vor kurzem, dass dies sehr nützlich ist, wenn wir Listener mit Standardmethoden deklarieren, können wir die mittlere Adapterklasse entfernen. zum Beispiel:

%Vor%     
holi-java 15.05.2017 17:45
quelle