Die Änderungen am Java 8-Interface umfassen statische Methoden und Standardmethoden in Interfaces. Vor Java 8 konnten wir nur Methodendeclarationen in den Interfaces haben. Aber ab Java 8 können wir Standardmethoden und statische Methoden in den Interfaces haben.
Java 8-Schnittstelle
Das Entwerfen von Schnittstellen war schon immer eine schwierige Aufgabe, denn wenn wir zusätzliche Methoden in den Schnittstellen hinzufügen wollen, erfordert dies Änderungen in allen implementierenden Klassen. Mit zunehmendem Alter der Schnittstelle kann die Anzahl der sie implementierenden Klassen so groß werden, dass eine Erweiterung der Schnittstellen nicht möglich ist. Deshalb bieten die meisten Frameworks bei der Entwicklung einer Anwendung eine Basisimplementierungsklasse an, die wir dann erweitern und Methoden überschreiben, die für unsere Anwendung relevant sind. Schauen wir uns die Standardmethoden in Schnittstellen und die statischen Schnittstellenmethoden sowie die Gründe für ihre Einführung in den Java 8-Interface-Änderungen an.
Java Interface Standardmethode
Für die Erstellung einer Standardmethode in einem Java-Interface müssen wir das Schlüsselwort „default“ zusammen mit der Methodensignatur verwenden. Zum Beispiel,
package com.journaldev.java8.defaultmethod;
public interface Interface1 {
void method1(String str);
default void log(String str){
System.out.println("I1 logging::"+str);
}
}
Beachten Sie, dass log(String str)
die Standardmethode in Interface1
ist. Wenn eine Klasse also Interface1
implementiert, ist es nicht zwingend erforderlich, eine Implementierung für Standardmethoden des Interfaces bereitzustellen. Diese Funktion ermöglicht es uns, Interfaces um zusätzliche Methoden zu erweitern. Alles, was wir tun müssen, ist eine Standardimplementierung bereitzustellen. Angenommen, wir haben ein weiteres Interface mit folgenden Methoden:
package com.journaldev.java8.defaultmethod;
public interface Interface2 {
void method2();
default void log(String str){
System.out.println("I2 logging::"+str);
}
}
Wir wissen, dass Java es nicht erlaubt, mehrere Klassen zu erweitern, da dies zum „Diamond-Problem“ führen würde, bei dem der Compiler nicht entscheiden kann, welche Superklassenmethode verwendet werden soll. Mit den Standardmethoden würde das Diamond-Problem auch für Interfaces auftreten. Denn wenn eine Klasse sowohl Interface1
als auch Interface2
implementiert und die gemeinsame Standardmethode nicht implementiert, kann der Compiler nicht entscheiden, welche Methode auszuwählen ist. Das Erweitern mehrerer Interfaces ist ein integraler Bestandteil von Java, und Sie werden es sowohl in den Kern-Java-Klassen als auch in den meisten Unternehmensanwendungen und Frameworks finden. Um sicherzustellen, dass dieses Problem in Interfaces nicht auftritt, muss daher eine Implementierung für gemeinsame Standardmethoden von Interfaces bereitgestellt werden. Wenn eine Klasse also beide oben genannten Interfaces implementiert, muss sie eine Implementierung für die log()
-Methode bereitstellen, sonst wirft der Compiler einen Kompilierungsfehler. Eine einfache Klasse, die sowohl Interface1
als auch Interface2
implementiert, wäre:
package com.journaldev.java8.defaultmethod;
public class MyClass implements Interface1, Interface2 {
@Override
public void method2() {
}
@Override
public void method1(String str) {
}
@Override
public void log(String str){
System.out.println("MyClass logging::"+str);
Interface1.print("abc");
}
}
Wichtige Punkte zu Java-Interface-Standardmethoden:
- Java-Schnittstellenvorgabemethoden helfen uns dabei, Schnittstellen zu erweitern, ohne die Angst zu haben, Implementierungsklassen zu brechen.
- Java-Schnittstellenvorgabemethoden haben die Unterschiede zwischen Schnittstellen und abstrakten Klassen überbrückt.
- Java 8-Schnittstellenvorgabemethoden helfen uns dabei, Hilfsklassen zu vermeiden. Alle Methoden der Collections-Klasse können in den Schnittstellen selbst bereitgestellt werden.
- Java-Schnittstellenvorgabemethoden helfen uns dabei, Basisklassenimplementierungen zu entfernen. Wir können eine Standardimplementierung bereitstellen, und die Implementierungsklassen können wählen, welche überschrieben werden soll.
- Einer der Hauptgründe für die Einführung von Vorgabemethoden in Schnittstellen besteht darin, die Collections-API in Java 8 zur Unterstützung von Lambda-Ausdrücken zu verbessern.
- Wenn eine Klasse in der Hierarchie eine Methode mit derselben Signatur hat, werden Vorgabemethoden irrelevant. Eine Vorgabemethode kann keine Methode aus
java.lang.Object
überschreiben. Der Grund ist einfach: Object ist die Basisklasse für alle Java-Klassen. Selbst wenn wir Methoden der Object-Klasse als Vorgabemethoden in Schnittstellen definiert haben, wäre es nutzlos, weil immer die Methode der Object-Klasse verwendet wird. Deshalb können wir, um Verwirrung zu vermeiden, keine Vorgabemethoden haben, die Methoden der Object-Klasse überschreiben. - Java-Schnittstellenvorgabemethoden werden auch als Verteidigungsmethoden oder virtuelle Erweiterungsmethoden bezeichnet.
Java-Schnittstellenstatische Methode
Die Java-Interface-Statikmethode ist ähnlich wie die Standardmethode, mit der Ausnahme, dass wir sie nicht in den Implementierungsklassen überschreiben können. Diese Funktion hilft uns, unerwünschte Ergebnisse bei schlechter Implementierung in den Implementierungsklassen zu vermeiden. Schauen wir uns das anhand eines einfachen Beispiels an.
package com.journaldev.java8.staticmethod;
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Jetzt sehen wir eine Implementierungsklasse, die die Methode isNull() mit einer schlechten Implementierung hat.
package com.journaldev.java8.staticmethod;
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Beachten Sie, dass isNull(String str)
eine einfache Klassenmethode ist und nicht die Schnittstellenmethode überschreibt. Wenn wir beispielsweise der Methode isNull() die @Override-Annotation hinzufügen, führt dies zu einem Compilerfehler. Wenn wir die Anwendung ausführen, erhalten wir folgende Ausgabe.
Interface Null Check
Impl Null Check
Wenn wir die Schnittstellenmethode von statisch auf Standard ändern, erhalten wir folgende Ausgabe.
Impl Null Check
MyData Print::
Impl Null Check
Die Java-Interface-Statikmethode ist nur für Schnittstellenmethoden sichtbar. Wenn wir die Methode isNull() aus der Klasse MyDataImpl
entfernen, können wir sie nicht für das Objekt MyDataImpl
verwenden. Wie andere statische Methoden können wir jedoch Schnittstellen-Statikmethoden mit dem Klassennamen verwenden. Ein gültiger Befehl wäre zum Beispiel:
boolean result = MyData.isNull("abc");
Wichtige Punkte zur Java-Interface-Statikmethode:
- Die Java-Interface-Statikmethode ist Teil der Schnittstelle, wir können sie nicht für Implementierungsklassenobjekte verwenden.
- Java-Interface-Statikmethoden eignen sich gut zur Bereitstellung von Hilfsmethoden, z. B. zur Nullüberprüfung, zur Sortierung von Sammlungen usw.
- Java Interface-Static-Methoden helfen uns, Sicherheit zu gewährleisten, indem sie Implementierungsklassen daran hindern, sie zu überschreiben.
- Wir können Interface-Static-Methoden nicht für Methoden der Object-Klasse definieren. Andernfalls erhalten wir einen Compilerfehler mit der Meldung „Diese statische Methode kann die Instanzmethode von Object nicht verbergen“. Dies ist in Java nicht erlaubt, da Object die Basisklasse für alle Klassen ist und wir keine statische Methodik auf Klassenebene und eine andere Instanzmethode mit der gleichen Signatur haben können.
- Wir können Java Interface-Static-Methoden verwenden, um Hilfsklassen wie Collections zu entfernen und alle ihre statischen Methoden in das entsprechende Interface zu verschieben. Dadurch wird es leichter zu finden und zu verwenden.
Java-Funktionsschnittstellen
Bevor ich den Beitrag abschließe, möchte ich eine kurze Einführung in Funktionsinterfaces geben. Eine Schnittstelle mit genau einer abstrakten Methode wird als Funktionsinterface bezeichnet. Eine neue Annotation @FunctionalInterface wurde eingeführt, um eine Schnittstelle als Funktionsinterface zu kennzeichnen. Die @FunctionalInterface-Annotation ist eine Möglichkeit, versehentliche Hinzufügungen von abstrakten Methoden in den funktionalen Schnittstellen zu vermeiden. Es ist optional, aber eine gute Praxis, sie zu verwenden. Funktionsinterfaces sind ein lang erwartetes und viel gesuchtes Feature von Java 8, weil es uns ermöglicht, sie mit Lambda-Ausdrücken zu instanziieren. Ein neues Paket java.util.function
mit einer Reihe von funktionalen Schnittstellen wurde hinzugefügt, um Zieltypen für Lambda-Ausdrücke und Methodenreferenzen bereitzustellen. Wir werden uns in zukünftigen Beiträgen mit funktionalen Schnittstellen und Lambda-Ausdrücken befassen.