1. Hintergrund der Einführung von Standardschnittstellenmethoden
Java8 kann als die Version angesehen werden, die sich im Iterationsprozess von Java-Versionsaktualisierungen am meisten geändert hat (wir sollten gerne mit der Zeit Schritt halten). Nach so vielen Jahren der Entwicklung und Iteration ist der Quellcode von Java jedoch zu einem Giganten geworden. Es ist definitiv nicht einfach, bei einem so großen Volumen einen großen Schritt zu machen. Als ich also zum ersten Mal die Standardschnittstellenmethoden von Java 8 sah, hatte ich zunächst das Gefühl, dass dies eine Lücke war, die von Java-Designern gegraben wurde, bevor sie sie füllten.
Aus den vorherigen Erklärungen wissen wir, dass Java8 der vorhandenen Schnittstelle viele Methoden hinzugefügt hat, beispielsweise die Methode sort(Comparator super E> c) von List. Wenn Sie den Entwurfsideen von Schnittstellen vor Java 8 folgen und einer Schnittstelle eine Methodendeklaration hinzufügen, muss die Klasse, die die Schnittstelle implementiert, eine entsprechende Implementierung für die neu hinzugefügte Methode hinzufügen. Aus Kompatibilitätsgründen ist dies nicht ratsam, daher stellt es eine Falle dar, und neue Funktionen erfordern das Hinzufügen einiger neuer Methoden zur Schnittstelle. Um den Kuchen zu haben und ihn auch zu essen, haben die Designer von Java8 die Standardschnittstellenmethode vorgeschlagen . Konzept.
Auf diese Weise scheint die Standardschnittstellenmethode für API-Designer entwickelt worden zu sein, was für uns normale Entwickler etwas verwirrend ist. Obwohl wir kein JDK entwerfen müssen, verwenden wir sie dennoch Während des Entwicklungsprozesses besteht weiterhin die Notwendigkeit, APIs für andere Geschäftsparteien bereitzustellen. Wenn wir unsere APIs aktualisieren, können wir die Standardmethode verwenden, um erweiterte Funktionen bereitzustellen und gleichzeitig die Kompatibilität aufrechtzuerhalten.
2. Definition der Standardschnittstellenmethode
Die Definition der Standardschnittstellenmethode ist sehr einfach. Fügen Sie einfach ein Standardschlüsselwort vor der Definition der Schnittstellenmethode hinzu, wie folgt:
public interface A { /** * 默认方法定义 */ default void method() { System.out.println("This is a default method!"); } }
Wenn wir eine Standardmethode wie diese definieren, enthalten alle Unterklassen, die diese Schnittstelle implementieren, indirekt diese Methode. Oder Sie denken vielleicht wie ich, dass Schnittstellen und abstrakte Klassen tatsächlich immer ähnlicher werden, es aber immer noch die folgenden Unterschiede zwischen ihnen gibt:
1. 一个类只能继承一个类,但是可以实现多个接口 2. 抽象类可以定义变量,而接口却不能
Zusätzlich zur Lösung der oben genannten Probleme, Abstraktion Außerdem hat es die folgenden Vorteile:
1. Für einige Methoden, die nicht von jeder Unterklasse benötigt werden, geben wir ihm eine Standardimplementierung, um bedeutungslose Implementierungen in Unterklassen zu vermeiden (im Allgemeinen werden wir neue UnsupportedException() auslösen) 2. Standardmethoden bieten eine neue Möglichkeit für die Mehrfachvererbung in Java (obwohl wir nur eine Klasse erben können, können wir mehrere Schnittstellen implementieren, und Schnittstellen können jetzt auch Standardmethoden definieren)
3. Konflikte und ihre Lösungen
Da eine Klasse mehrere Schnittstellen implementieren kann und zwei oder mehr Methodensignaturen in diesen Schnittstellen vorhanden sind, treten bei der Verwendung von Standardmethoden Konflikte auf. Java 8 definiert die folgenden drei Prinzipien So lösen Sie Konflikte:
1. Explizit deklarierte Methoden in einer Klasse oder übergeordneten Klasse haben eine höhere Priorität als alle Standardmethoden. 2. Wenn eine Regel fehlschlägt, wählen Sie die Standardmethode mit einer bestimmten Implementierung aus, die dieser am nächsten kommt 3. Wenn Regel 2 ebenfalls fehlschlägt, müssen Sie die Schnittstelle explizit angeben
Das Folgende wird anhand mehrerer Beispiele erklärt:
Beispiel 1
public interface A { /** * 默认方法定义 */ default void method() { System.out.println("A's default method!"); } }public interface B extends A { /** * 默认方法定义 */ default void method() { System.out.println("B's default method!"); } }public class C implements A, B { public static void main(String[] args) { new C().method(); } }// 输出:B's default method!
Da Schnittstelle B näher an C als A liegt und die Methode von B gemäß Regel 2 eine bestimmte Standardimplementierung ist, wird hier tatsächlich die Standardmethode von Schnittstelle B genannt
Beispiel 2
public class D implements A { }public class C extends D implements A, B { public static void main(String[] args) { new C().method(); } }// 输出:B's default method!
Beispiel 2 fügt eine Klasse D hinzu, die die Schnittstelle A auf der Grundlage der ursprünglichen Schnittstellen A und B implementiert, und dann erbt Klasse C von D und implementiert A und B. Obwohl C näher an D liegt Da sich hier die spezifische Implementierung von D in A befindet, ist die Standardmethode in B immer noch die nächstgelegene Standardimplementierung. Gemäß Regel 2 wird hier tatsächlich die Standardmethode von B genannt.
Beispiel 3
// A接口不变public interface B { /** * 默认方法定义 */ default void method() { System.out.println("B's default method!"); } }public class C implements A, B { @Override public void method() { // 必须显式指定 B.super.method(); } public static void main(String[] args) { new C().method(); } }
In Beispiel 3 erbt Schnittstelle B nicht mehr von Schnittstelle A, daher hat die in C aufgerufene Standardmethode method() zu diesem Zeitpunkt den gleichen Abstand von der Spezifische Implementierung der Schnittstellen A und B. Der Compiler kann dies nicht ermitteln, daher wird ein Fehler gemeldet. In diesem Fall müssen Sie Folgendes explizit angeben: B.super.method().