JavaRush /Java-Blog /Random-DE /Standardmethoden in Java 8: Was können sie und was nicht?...
Spitfire
Level 33

Standardmethoden in Java 8: Was können sie und was nicht?

Veröffentlicht in der Gruppe Random-DE
Übersetzung eines Artikels von Peter Verhas vom April 2014. Standardmethoden in Java 8: Was können sie und was nicht?  - 1Vom Übersetzer: Der Begriff „ Standardmethode “ ist gerade in Java aufgetaucht und ich bin mir nicht sicher, ob es dafür eine etablierte Übersetzung ins Russische gibt. Ich verwende den Begriff „Standardmethode“, obwohl ich das nicht für ideal halte. Ich lade Sie ein, eine erfolgreichere Übersetzung zu besprechen.

Was ist die Standardmethode?

Mit der Veröffentlichung von Java 8 können Sie Schnittstellen jetzt neue Methoden hinzufügen, sodass die Schnittstelle mit den Klassen kompatibel bleibt, die sie implementieren. Dies ist sehr wichtig, wenn Sie eine Bibliothek entwickeln, die von vielen Programmierern von Kiew bis New York verwendet wird. Wenn Sie vor Java 8 eine Schnittstelle in einer Bibliothek definiert haben, konnten Sie ihr keine Methoden hinzufügen, ohne das Risiko einzugehen, dass eine Anwendung, die Ihre Schnittstelle ausführt, bei der Aktualisierung kaputt geht. In Java 8 können Sie davor also keine Angst mehr haben? Nein, geht nicht. Das Hinzufügen einer Standardmethode zu einer Schnittstelle kann dazu führen, dass einige Klassen unbrauchbar werden. Schauen wir uns zunächst die Vorteile von Standardmethoden an. In Java 8 kann die Methode direkt in der Schnittstelle implementiert werden. (Statische Methoden in einer Schnittstelle können mittlerweile auch implementiert werden, aber das ist eine andere Geschichte.) Eine in einer Schnittstelle implementierte Methode wird als Standardmethode bezeichnet und mit dem Schlüsselwort „default“ bezeichnet . Wenn eine Klasse eine Schnittstelle implementiert, kann sie die in der Schnittstelle implementierten Methoden implementieren, muss dies jedoch nicht. Die Klasse erbt die Standardimplementierung. Aus diesem Grund ist es nicht erforderlich, Klassen zu ändern, wenn die von ihnen implementierte Schnittstelle geändert wird.

Mehrfachvererbung?

Komplizierter wird es, wenn eine Klasse mehr als eine (z. B. zwei) Schnittstellen implementiert und diese dieselbe Standardmethode implementieren. Welche Methode wird die Klasse erben? Die Antwort ist keine. In diesem Fall muss die Klasse die Methode selbst implementieren (entweder direkt oder durch Vererbung von einer anderen Klasse). Ähnlich verhält es sich, wenn nur eine Schnittstelle eine Standardmethode hat und in der anderen Schnittstelle dieselbe Methode abstrakt ist. Java 8 versucht, diszipliniert zu sein und unklare Situationen zu vermeiden. Wenn Methoden in mehr als einer Schnittstelle deklariert sind, wird keine Standardimplementierung von der Klasse geerbt – Sie erhalten einen Kompilierungsfehler. Allerdings erhalten Sie möglicherweise keinen Kompilierungsfehler, wenn Ihre Klasse bereits kompiliert ist. Java 8 ist in dieser Hinsicht nicht robust genug. Dafür gibt es Gründe, auf die ich nicht näher eingehen möchte (zum Beispiel: Das Java-Release ist bereits veröffentlicht und die Zeit für Diskussionen ist längst vorbei und im Allgemeinen ist dies nicht der richtige Ort dafür).
  • Nehmen wir an, Sie haben zwei Schnittstellen und eine Klasse implementiert beide.
  • Eine der Schnittstellen implementiert die Standardmethode m().
  • Sie kompilieren alle Schnittstellen und die Klasse.
  • Sie ändern eine Schnittstelle, die keine m()-Methode hat, indem Sie sie als abstrakte Methode deklarieren.
  • Sie kompilieren nur die geänderte Schnittstelle.
  • Starten Sie den Unterricht.
Standardmethoden in Java 8: Was können sie und was nicht?  - 2In diesem Fall funktioniert die Klasse. Man kann es nicht mit den aktualisierten Schnittstellen kompilieren, aber es wurde mit älteren Versionen kompiliert und funktioniert daher. Jetzt
  • Ändern Sie die Schnittstelle mit der abstrakten m()-Methode und fügen Sie eine Standardimplementierung hinzu.
  • Kompilieren Sie die geänderte Schnittstelle.
  • Klasse ausführen: Fehler.
Wenn es zwei Schnittstellen gibt, die eine Standardimplementierung einer Methode bereitstellen, kann diese Methode nicht in einer Klasse aufgerufen werden, es sei denn, sie wird von der Klasse selbst implementiert (wiederum entweder eigenständig oder von einer anderen Klasse geerbt). Standardmethoden in Java 8: Was können sie und was nicht?  - 3Klassenkompatibel. Es kann mit einer modifizierten Schnittstelle geladen werden. Es kann sogar so lange ausgeführt werden, bis eine Methode aufgerufen wird, die in beiden Schnittstellen über eine Standardimplementierung verfügt.

Beispielcode

Standardmethoden in Java 8: Was können sie und was nicht?  - 4Um das oben Gesagte zu demonstrieren, habe ich ein Testverzeichnis für die Klasse C.java und drei Unterverzeichnisse für die Schnittstellen in den Dateien I1.java und I2.java erstellt. Das Stammverzeichnis für den Test enthält den Quellcode für die Klasse C.java. Das Basisverzeichnis enthält eine Version der Schnittstellen, die zur Ausführung und Kompilierung geeignet sind: Schnittstelle I1 verfügt über eine Standardmethode m(); Die I2-Schnittstelle verfügt noch über keine Methoden. Die Klasse verfügt über eine Methode main, mit der wir sie zum Testen ausführen können. Es prüft, ob Befehlszeilenargumente vorhanden sind, sodass wir es problemlos mit oder ohne Aufruf von ausführen können m().
~/github/test$ cat C.java
public class C implements I1, I2 {
  public static void main(String[] args) {
    C c = new C();
    if( args.length == 0 ){
      c.m();
    }
  }
}
~/github/test$ cat base/I1.java
public interface I1 {
  default void m(){
    System.out.println("hello interface 1");
  }
}
~/github/test$ cat base/I2.java
public interface I2 {
}
Sie können die Klasse über die Befehlszeile kompilieren und ausführen.
~/github/test$ javac -cp .:base C.java
~/github/test$ java -cp .:base C
hello interface 1
Das kompatible Verzeichnis enthält eine Version der I2-Schnittstelle, die die m()-Methode als abstrakt deklariert, und aus technischen Gründen auch eine unveränderte Kopie von I1.java.
~/github/test$ cat compatible/I2.java

public interface I2 {
  void m();
}
Ein solcher Satz kann nicht zum Kompilieren einer C-Klasse verwendet werden:
~/github/test$ javac -cp .:compatible C.java
C.java:1: error: C is not abstract and does not override abstract method m() in I2
public class C implements I1, I2 {
       ^
1 error
Die Fehlermeldung ist sehr genau. Wir haben jedoch C.class aus einer früheren Kompilierung und wenn wir die Schnittstellen in das kompatible Verzeichnis kompilieren, verfügen wir über zwei Schnittstellen, die weiterhin zum Ausführen der Klasse verwendet werden können:
~/github/test$ javac compatible/I*.java
~/github/test$ java -cp .:compatible C
hello interface 1
Das dritte Verzeichnis - wrong- enthält Version I2, die auch die Methode deklariert m():
~/github/test$ cat wrong/I2.java
public interface I2 {
  default void m(){
    System.out.println("hello interface 2");
  }
}
Sie müssen sich nicht einmal um die Zusammenstellung kümmern. Auch wenn die Methode zweimal deklariert wird, kann die Klasse weiterhin verwendet und ausgeführt werden, bis die m()-Methode aufgerufen wird. Dafür benötigen wir das Befehlszeilenargument:
~/github/test$ javac wrong/*.java
~/github/test$ java -cp .:wrong C
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: I1.m I2.m
    at C.m(C.java)
    at C.main(C.java:5)
~/github/test$ java -cp .:wrong C x
~/github/test$

Abschluss

Wenn Sie Ihre Bibliothek auf Java 8 portieren und Ihre Schnittstellen so ändern, dass sie Standardmethoden enthalten, werden Sie wahrscheinlich keine Probleme haben. Zumindest hoffen die Entwickler der Java 8-Bibliothek darauf, wenn sie Funktionalität hinzufügen. Anwendungen, die Ihre Bibliothek verwenden, verwenden sie immer noch für Java 7, wo es keine Standardmethoden gibt. Bei der gemeinsamen Nutzung mehrerer Bibliotheken kann es zu Konflikten kommen. Wie kann man es vermeiden? Entwerfen Sie die API Ihrer Bibliothek auf die gleiche Weise wie zuvor. Seien Sie nicht selbstgefällig, indem Sie sich auf die Fähigkeiten der Standardmethoden verlassen. Sie sind der letzte Ausweg. Wählen Sie Namen sorgfältig aus, um Kollisionen mit anderen Schnittstellen zu vermeiden. Mal sehen, wie sich die Entwicklung für Java mit dieser Funktion entwickeln wird.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION