Entwicklungsgeschichte der Schnittstellen in Java

Bild

Die Oberfläche in Java hat sich im Laufe der Jahre stark weiterentwickelt. Schauen wir uns an, welche Veränderungen im Verlauf der Entwicklung eingetreten sind.

Originelle Schnittstellen


Die Schnittstellen in Java 1.0 waren im Vergleich zu den heutigen recht einfach. Sie können nur zwei Arten von Elementen enthalten: Konstanten und öffentliche abstrakte Methoden.

Konstante Felder


Schnittstellen können Felder enthalten, genau wie reguläre Klassen, jedoch mit ein paar Unterschieden:

  • Felder müssen initialisiert werden.
  • Felder gelten als public static final
  • Die Modifikatoren public, static und final müssen nicht explizit angegeben werden (sie werden standardmäßig "abgelegt")

public interface MyInterface { int MY_CONSTANT = 9; } 

Obwohl dies nicht explizit angegeben ist, wird das Feld MY_CONSTANT als öffentliche statische Endkonstante betrachtet. Sie können diese Modifikatoren hinzufügen, dies ist jedoch nicht erforderlich.

Abstrakte Methoden


Die wichtigsten Elemente einer Schnittstelle sind ihre Methoden. Schnittstellenmethoden unterscheiden sich auch von regulären Klassenmethoden:

  • Methoden haben keinen Körper
  • Die Implementierung der Methode wird von Klassen bereitgestellt, die diese Schnittstelle implementieren.
  • Methoden gelten als öffentlich und abstrakt, auch wenn sie nicht explizit angegeben sind.
  • Methoden können nicht final sein, da die Kombination von abstrakten und finalen Modifikatoren in Java nicht zulässig ist

 public interface MyInterface { int doSomething(); String doSomethingCompletelyDifferent(); } 

Nisten


In Java 1.1 wurde das Konzept von Klassen eingeführt, die in andere Klassen eingefügt werden können. Es gibt zwei Arten solcher Klassen: statische und nicht statische. Schnittstellen können auch andere Schnittstellen und Klassen enthalten.

Auch wenn dies nicht explizit angegeben wird, werden solche Schnittstellen und Klassen als öffentlich und statisch betrachtet.

 public interface MyInterface { class MyClass { //... } interface MyOtherInterface { //... } } 

Aufzählungen und Anmerkungen


In Java 5 wurden zwei weitere Typen eingeführt: Aufzählungen und Anmerkungen. Sie können auch in Schnittstellen platziert werden.

 public interface MyInterface { enum MyEnum { FOO, BAR; } @interface MyAnnotation { //... } } 

Generische Typen


Java 5 führte das Konzept der generischen Typen ein. Kurz gesagt: Mit Generika können Sie einen generischen Typ verwenden, anstatt einen bestimmten Typ anzugeben. Auf diese Weise können Sie Code schreiben, der mit einer anderen Anzahl von Typen arbeitet, ohne die Sicherheit zu beeinträchtigen und ohne für jeden Typ eine separate Implementierung bereitzustellen.

In Interfaces, die in Java 5 beginnen, können Sie einen generischen Typ definieren und ihn dann als Typ des Rückgabewerts einer Methode oder als Typ eines Arguments für eine Methode verwenden.

Die Box-Oberfläche funktioniert unabhängig davon, ob Sie sie zum Speichern von Objekten wie String, Integer, List, Shoe oder anderen verwenden.

 interface Box<T> { void insert(T item); } class ShoeBox implements Box<Shoe> { public void insert(Shoe item) { //... } } 

Statische Methoden


Ab Java 8 können Sie statische Methoden in Schnittstellen einbinden. Dieser Ansatz hat die Funktionsweise der Benutzeroberfläche für uns geändert. Sie funktionieren jetzt ganz anders als vor Java 8. Zu Beginn waren alle Methoden in den Schnittstellen abstrakt. Dies bedeutete, dass die Schnittstelle nur eine Signatur, aber keine Implementierung bereitstellte. Die Implementierung wurde den Klassen überlassen, die Ihre Schnittstelle implementieren.

Wenn Sie statische Methoden in Schnittstellen verwenden, müssen Sie auch eine Implementierung des Methodenkörpers bereitstellen. Um diese Methode in einer Schnittstelle zu verwenden, verwenden Sie einfach das Schlüsselwort static. Statische Methoden werden standardmäßig als öffentlich betrachtet.

 public interface MyInterface { // This works static int foo() { return 0; } // This does not work, // static methods in interfaces need body static int bar(); } 

Statische Methodenvererbung


Im Gegensatz zu regulären statischen Methoden werden statische Methoden in Schnittstellen nicht vererbt. Das heißt, wenn Sie eine solche Methode aufrufen möchten, müssen Sie sie direkt von der Schnittstelle aus aufrufen und nicht von der Klasse, die sie implementiert.

 MyInterface.staticMethod(); 

Dieses Verhalten ist sehr nützlich, um Probleme mit der Mehrfachvererbung zu vermeiden. Stellen Sie sich vor, Sie haben eine Klasse, die zwei Schnittstellen implementiert. Jede der Schnittstellen verfügt über eine statische Methode mit demselben Namen und derselben Signatur. Welches sollte zuerst verwendet werden?

Warum ist es nützlich?


Stellen Sie sich vor, Sie haben eine Schnittstelle und eine ganze Reihe von Hilfsmethoden, die mit Klassen arbeiten, die diese Schnittstelle implementieren.

Traditionell gab es einen Ansatz zur Verwendung einer Companion-Klasse. Zusätzlich zur Schnittstelle wurde eine Utility-Klasse mit einem sehr ähnlichen Namen erstellt, die statische Methoden enthält, die zur Schnittstelle gehören.

Beispiele für die Verwendung dieses Ansatzes finden Sie direkt im JDK: Die Schnittstelle java.util.Collection und die zugehörige Dienstprogrammklasse java.util.Collections.

Bei statischen Methoden in den Schnittstellen ist dieser Ansatz nicht mehr relevant, wird nicht benötigt und nicht empfohlen. Jetzt können Sie alles an einem Ort haben.

Standardmethoden


Standardmethoden sind statischen Methoden insofern ähnlich, als Sie auch einen Body für sie bereitstellen müssen. Verwenden Sie zum Deklarieren einer Standardmethode einfach das Standardschlüsselwort.

 public interface MyInterface { default int doSomething() { return 0; } } 

Im Gegensatz zu statischen Methoden werden Methoden standardmäßig von Klassen geerbt, die die Schnittstelle implementieren. Was wichtig ist, können solche Klassen bei Bedarf ihr Verhalten neu definieren.

Obwohl es eine Ausnahme gibt. Die Schnittstelle darf keine Standardmethoden mit derselben Signatur wie die Methoden toString, equals und hashCode der Object-Klasse haben. Schauen Sie sich die Antwort von Brian Goetz an, um die Gültigkeit einer solchen Lösung zu verstehen: Lassen Sie zu, dass Standardmethoden die Methoden von Object überschreiben.

Warum ist es nützlich?


Die Idee, Methoden direkt in die Oberfläche zu implementieren, scheint nicht ganz richtig zu sein. Warum wurde diese Funktionalität zum ersten Mal eingeführt?

Schnittstellen haben ein Problem. Sobald Sie Ihre API an andere Personen weitergeben, wird sie für immer „versteinern“ (sie kann nicht schmerzlos geändert werden).

Java nimmt traditionell die Abwärtskompatibilität sehr ernst. Die Standardmethoden bieten eine Möglichkeit, vorhandene Schnittstellen mit neuen Methoden zu erweitern. Vor allem bieten die Standardmethoden bereits eine bestimmte Implementierung. Dies bedeutet, dass Klassen, die Ihre Schnittstelle implementieren, keine neuen Methoden implementieren müssen. Bei Bedarf können die Standardmethoden jedoch jederzeit überschrieben werden, wenn ihre Implementierung nicht mehr geeignet ist. Kurz gesagt, Sie können vorhandenen Klassen, die Ihre Schnittstelle implementieren, neue Funktionen bereitstellen und gleichzeitig die Kompatibilität aufrechterhalten.

Konflikte


Stellen wir uns vor, wir haben eine Klasse, die zwei Interfaces implementiert. Diese Schnittstellen haben eine Standardmethode mit demselben Namen und derselben Signatur.

 interface A { default int doSomething() { return 0; } } interface B { default int doSomething() { return 42; } } class MyClass implements A, B { } 

Nun wird dieselbe Standardmethode mit derselben Signatur von zwei verschiedenen Schnittstellen geerbt. Jede Schnittstelle hat eine eigene Implementierung dieser Methode.

Woher weiß unsere Klasse, welche der beiden verschiedenen Implementierungen sie verwenden soll?

Er wird es nicht wissen. Der obige Code führt zu einem Kompilierungsfehler. Wenn es funktionieren soll, müssen Sie die in Konflikt stehende Methode in Ihrer Klasse überschreiben.

 interface A { default int doSomething() { return 0; } } interface B { default int doSomething() { return 42; } } class MyClass implements A, B { // Without this the compilation fails @Override public int doSomething() { return 256; } } 

Private Methoden


Mit dem Aufkommen von Java 8 und der Einführung von Standardmethoden und statischen Methoden können Schnittstellen nicht nur Methodensignaturen, sondern auch deren Implementierung enthalten. Beim Schreiben solcher Implementierungen wird empfohlen, komplexe Methoden in einfachere zu unterteilen. Solcher Code ist einfacher wiederzuverwenden, zu warten und zu verstehen.

Zu diesem Zweck würden Sie private Methoden verwenden, da diese alle Implementierungsdetails enthalten können, die nicht sichtbar sein und von außen verwendet werden sollten.

In Java 8 kann eine Schnittstelle leider keine privaten Methoden enthalten. Dies bedeutet, dass Sie Folgendes verwenden können:

  1. Lange, komplexe und schwer verständliche Körpertechniken.
  2. Hilfsmethoden, die Teil der Schnittstelle sind. Dies verstößt gegen das Prinzip der Kapselung und belastet die öffentliche API der Schnittstellen- und Implementierungsklassen.

Glücklicherweise können Sie ab Java 9 private Methoden in Interfaces verwenden . Sie haben folgende Eigenschaften:

  • Private Methoden haben einen Körper, sie sind nicht abstrakt
  • Sie können entweder statisch oder nicht statisch sein
  • Sie werden nicht von Klassen geerbt, die die Schnittstelle und die Schnittstellen implementieren
  • Sie können andere Schnittstellenmethoden aufrufen
  • Private Methoden können andere private, abstrakte, statische oder Standardmethoden aufrufen
  • Private statische Methoden können nur andere statische und private statische Methoden aufrufen

 public interface MyInterface { private static int staticMethod() { return 42; } private int nonStaticMethod() { return 0; } } 

Chronologische Reihenfolge


Das Folgende ist eine chronologische Liste der Änderungen für Java-Versionen:

Java 1.1


Geschachtelte Klassen

Verschachtelte Schnittstellen

Java 5


Generische Typen

Anbei Transfers

Verschachtelte Anmerkungen

Java 8


Standardmethoden

Statische Methoden

Java 9


Private Methoden

Source: https://habr.com/ru/post/de482498/


All Articles