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 den vorhandenen Schnittstellen viele Methoden hinzugefügt hat, beispielsweise die Methode sort(Comparator0d74ac1b2f8f9ab0eb66f930789a9645 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 zwar immer ähnlicher werden, es aber immer noch die folgenden Unterschiede zwischen ihnen gibt:
Eine Klasse kann nur eine Klasse erben, Sie können jedoch mehrere Schnittstellen implementieren
Abstrakte Klassen können Variablen definieren, Schnittstellen jedoch nicht
Zusätzlich zur Lösung der oben genannten Probleme bietet die Abstraktion auch die folgenden Vorteile:
1. Für einige Methoden, die nicht von jeder Unterklasse benötigt werden, geben wir eine Standardimplementierung, um bedeutungslose Implementierungen in Unterklassen zu vermeiden (im Allgemeinen werden wir neue UnsupportedException() auslösen)
Standard Methoden 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, treten diese Konflikte auf, wenn zwei oder mehr Standardmethoden mit derselben Methodensignatur vorhanden sind Die Schnittstelle. Java8 definiert die folgenden drei Prinzipien, um Konflikte zu lösen:
1 Für Methoden, die explizit in einer Klasse oder übergeordneten Klasse deklariert werden, ist die Priorität höher als bei allen Standardmethoden
2. Wenn Regel 1 fehlschlägt, wählen Sie die Standardmethode mit einer bestimmten Implementierung aus, die der aktuellen Klasse am nächsten kommt
3. Wenn Regel 2 fehlschlägt, benötigen Sie um die Schnittstelle explizit anzugeben
Das Folgende wird anhand mehrerer Beispiele erklärt:
Beispiel 1
Hier, weil Schnittstelle B näher an C als A liegt, und die Methode von B ist gemäß Regel 2 eine spezifische Standardimplementierung, daher wird hier tatsächlich die Standardmethode von Schnittstelle B aufgerufenpublic 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!
Beispiel 2
Beispiel 2 fügt eine Klasse D hinzu, die die Schnittstelle implementiert A basiert auf den ursprünglichen Schnittstellen A und B. Dann erbt Klasse C von D und implementiert A und B. Obwohl C hier näher an D liegt, ist die Standardmethode in B immer noch am nächsten, da sich die spezifische Implementierung von D in A befindet Gemäß Regel 2 wird hier tatsächlich die Standardmethode von B aufgerufen.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 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(); } }
例3中接口B不再继承自接口A,所以此时C中调用默认方法method()距离接口A和B的具体实现距离相同,编译器无法确定,所以报错,此时需要显式指定:B.super.method()。