Was sind Java 8-Schnittstellen und wie werden sie verwendet?
In Java funktioniert eine Schnittstelle ähnlich wie eine abstrakte Klasse, was bedeutet, dass ein Objekt niemals aus einer Schnittstelle erzeugt werden kann. Aus diesem Grund hat eine Schnittstelle keine Konstruktoren, aber Methoden.
Vor Java 8 konnte eine Schnittstelle die Operationen beschreiben, die ihre implementierende Klasse ausführt, aber nicht, wie die implementierende Klasse diese Operation ausführen sollte (dazu später mehr). Mit Java 8 kann ein Entwickler jetzt beides mit einer Schnittstelle tun.
Dies liegt daran, dass Java 8 Standardschnittstellenmethoden eingeführt hat. Entwickler haben damit nun die Möglichkeit, sowohl traditionelle abstrakte Methoden als auch die neuen konkreten Methoden innerhalb einer Schnittstelle zu verwenden. Lasst uns genauer hinschauen.
Was ist eine Schnittstelle?
Bevor Sie den Zweck einer Schnittstelle und ihre effektive Nutzung wirklich verstehen können, müssen Sie den Polymorphismus verstehen. Polymorphismus ist ein Kernkonzept der objektorientierten Programmierung, das es einem Entwickler ermöglicht, verallgemeinertes und spezialisiertes Verhalten mit Klassen zu erzeugen (die in einigen Fällen nicht direkt miteinander verbunden sind).
Der Hauptvorteil des Polymorphismus besteht darin, dass er die Wiederverwendung von Code erleichtert, was in der heutigen Softwareentwicklungsbranche von entscheidender Bedeutung ist.
Wie verhält sich Polymorphismus zu einer Java-Schnittstelle? In Java ermöglicht eine Schnittstelle Klassen, die konventionell nicht in Beziehung stehen würden, Zugriff auf ähnliche Operationen. In seiner einfachsten Form ist eine Java-Schnittstelle eine Vorlage, die von den verschiedenen Klassen, die sie implementieren, leicht verwendet werden kann. Diese implementierenden Klassen können dann die Methode einer Schnittstelle von ihrem generalisierten Zustand in einen spezialisierteren Zustand umwandeln, um eine bestimmte Aufgabe zu erfüllen.
Was sind die Vorteile der Verwendung von Java 8-Schnittstellen?
Der offensichtlichste Vorteil der Verwendung einer Java 8-Schnittstelle ist ihre neue konkrete Methodenfähigkeit.
Ein weiterer willkommener Vorteil von Java 8 Interfaces ist die Möglichkeit, einer bestehenden, bereits implementierten Schnittstelle neue konkrete Methoden hinzuzufügen, ohne das Programm zu zerstören. Wenn Sie vor Java 8 eine Klasse hatten, die eine Schnittstelle implementiert, aber nicht alle ihre Methoden verwendet, müsste diese Klasse als abstrakt gekennzeichnet werden. Andernfalls würde das Programm abbrechen.
Wann sollten Sie eine Schnittstelle verwenden?
Viele existierende Programme können potenziell Java 8-Schnittstellen verwenden. Die Funktion einer Schnittstelle besteht darin, das Leben eines Programmierers zu erleichtern. Obwohl die gleiche Funktionalität ohne Schnittstellen erreicht werden kann, werden Ihre Programme durch deren Verwendung organisierter und Ihr Entwicklungsprozess weniger zeitaufwändig.
Wenn Sie mit Vererbung vertraut sind, sollten Sie wissen, dass dies auch ein Kernkonzept der objektorientierten Programmierung ist, das die Verallgemeinerung erleichtert. Bei der Vererbung werden ähnliche Klassen in Eltern-Kind-Beziehungen gruppiert.
Mit Polymorphismus (das ist das Programmierverhalten, das eine Schnittstelle zeigt) können Klassen, die normalerweise keinen Zugriff auf dieselben Methoden hätten (wegen fehlender Eltern-Kind-Beziehungen), jetzt polymorph verarbeitet werden.
Ein praktisches Beispiel für die Verwendung einer Schnittstelle ist die Buchhaltung eines Softwareunternehmens. Diese Abteilung wird höchstwahrscheinlich eine Reihe derselben Methoden (oder Vorgänge) durchführen, wenn sie die Gehaltsabrechnung eines Mitarbeiters und eine Kundenrechnung erstellt.
Dies sind zwei Klassen, die konventionell nicht miteinander verwandt wären, aber dank der Java-8-Schnittstellen können sie jetzt einige der gleichen Operationen verwenden.
Erstellen einer Schnittstelle in Java
Mit dem obigen Szenario der Buchhaltung können Sie eine Schnittstelle erstellen, die sich mit Zahlungsvorgängen befasst. Der Zweck dieser Schnittstelle besteht darin, bei der Erstellung von Zahlungsberichten (in Form von Rechnungen, Gehaltsabrechnungen und anderen Ausgaben) zu helfen.
Erstellen eines Java-Interface-Beispiels
//Java interface
public interface Payable {
//abstract method public void paymentAmount();
}
Der obige Code generiert eine einfache Java-Schnittstelle. Das Schlüsselwort interface gibt an, dass Payable eine Schnittstelle und die Methode paymentAmount() eine abstrakte Methode ist, da sie nicht implementiert ist.
Implementieren des Zahlungsschnittstellenbeispiels
public class Employee implements Payable {
//attributes
private String name; private String position;
//primary constructor
public Employee (String name, String position) {
this.name = name; this.position = position;
}
//payLevel method - takes an employee's position and returns their pay
public double payLevel(String position) {
position.toLowerCase();
if (position == "junior" ) {
return 10.00;
}
if(position == "mid-level") {
return 20.0;
}
if(position == "senior") {
return 30.00;
}
return 0 ;
}
@Override public void paymentAmount() {
//passes the position attribute provided by the user to the payLevel() method above
// store the return from the function call to a double variable called pay
//and print the relevant data to the console
double pay = payLevel(position);
System.out.println(name + " pay for this month is: " + pay);
}
}
Um eine Schnittstelle in einer Klasse zu verwenden, müssen Sie diese Schnittstelle zunächst mit dem Schlüsselwort implement implementieren , wie Sie im obigen Code sehen können. Nach der Implementierung einer neuen Schnittstelle sollten Sie mit dem Schlüsselwort @Override konkrete Methoden für alle abstrakten Methoden in der Schnittstelle erstellen .
Ausführen des Programmbeispiels
public class Main {
public static void main(String[] args) {
//Create a new employee pay report
Payable JanesPay = new Employee ("Jane Doe", "mid-level");
//calculate the employee's pay
JanesPay.paymentAmount();
}
}
Das obige Programm verwendet die Employee- Klasse, um eine neue Gehaltsabrechnung zu generieren, die die Payable- Schnittstelle verwendet. Ein Objekt kann nicht aus einer Schnittstelle erstellt werden, aber ein Objekt kann mit einer Schnittstelle deklariert werden, wie Sie im obigen Code sehen können.
Das Gehaltsobjekt der Jane wird mit zwei Attributen erstellt – dem Namen eines Mitarbeiters und der Position des Mitarbeiters im Unternehmen. Es gibt nur einen primären Konstruktor in der Employee- Klasse, daher muss jedes neu erstellte Employee-Objekt zwei Zeichenfolgenattribute haben.
Mit dem Pay- Objekt von Jane ruft das Programm die Methode paymentAmount() in der Employee- Klasse auf, die in der Konsole folgende Ausgabe erzeugt:
Jane Doe pay for this month is: 20.0
Implementierung der Zahlungsschnittstelle mit Kundenbeispiel
public class Customer implements Payable{
private String customerName;
private String projectType;
public Customer(String customerName, String projectType) {
this.customerName = customerName;
this.projectType = projectType;
}
public double customerInvoice(String projectType) {
projectType.toLowerCase();
if (projectType == "small" ) {
return 10.00;
}
if(projectType == "medium") {
return 20.0;
}
if(projectType == "large") {
return 30.00;
}
return 0 ;
}
@Override public void paymentAmount() {
double total = customerInvoice(projectType);
System.out.println(customerName + " total charge for services provided is: " + total);
}
}
Die Mitarbeiter- und Kundenklassen haben keinen Bezug zueinander, aber da sie alle dieselbe Schnittstelle implementieren, haben sie jetzt Zugriff auf ähnliche Operationen. Wie die Employee- Klasse muss die Customer- Klasse die Schnittstelle implementieren und die abstrakte Methode paymentAmount() überschreiben, um korrekt zu funktionieren.
Die gleichen Operationen, die an einem Objekt der Klasse Mitarbeiter durchgeführt wurden , können nun auch an einem Objekt der Klasse Kunden durchgeführt werden .
Beispiel für ein Kundenobjekt erstellen
public class Main {
public static void main(String[] args) {
//Create a new customer invoice report
Payable PaulsInvoice = new Customer("Paul Smith", "large");
//calculate the customer's pay
PaulsInvoice.paymentAmount();
}
}
Der obige Code generiert die folgende Ausgabe in der Konsole:
Paul Smith total charge for services provided is: 30.0
Da es sich bei der Schnittstelle um eine Java 8-Schnittstelle handelt, können Sie ihr Standardmethoden hinzufügen, ohne den Code zu beschädigen, wie Sie im folgenden Beispiel sehen können.
Aktualisieren eines Java 8-Schnittstellenbeispiels
//Java interface
public interface Payable {
//abstract method
public abstract void paymentAmount();
//concrete method
public default void companyName() {
System.out.println("Software Company");
}
}
Vor Java 8 würde das Hinzufügen der konkreten Methode im obigen Code zu Ihrer Schnittstelle die Schnittstelle beschädigen. Dies liegt daran, dass Schnittstellen vor Java 8 keine konkreten Methoden haben konnten. Wenn die Methode jedoch abstrakt ist, bleibt die Schnittstelle unberührt. Aber Klassen, die es implementiert haben, bevor die neue Methode hinzugefügt wurde, würden brechen.
Aufgrund von Java 8 werden durch das Hinzufügen konkreter Methoden zu einer Schnittstelle keine Klassen zerstört, die bereits implementiert wurden. Daher können Objekte, die aus einer der beiden Implementierungsklassen in diesem Kontoverwaltungsbeispiel erstellt wurden, die Methode companyName() verwenden, ohne ihren vorhandenen Code zu ändern.
Beispiel für eine Standardmethode für die Java 8-Schnittstelle
public class Main {
public static void main(String[] args) {
//Create a new employee pay report
Payable JanesPay = new Employee("Jane Doe", "mid-level");
//call the default method from the interface
JanesPay.companyName();
//calculate the employee's pay
JanesPay.paymentAmount();
}
}
Der obige Code erzeugt in der Konsole Folgendes:
Software Company
Jane Doe pay for this month is: 20.0
Verwenden der Generalisierung zum Erstellen von wiederverwendbarem Code
Jetzt können Sie mit Hilfe von Java 8 Interfaces ähnliche Operationen für Klassen verwenden, die konventionell nicht miteinander verbunden sind. Außerdem haben Sie die Möglichkeit und das Wissen, sowohl konkrete als auch abstrakte Methoden in Ihren Schnittstellen einzusetzen.
Bei Klassen, die konventionell verwandt sind, können Sie jedoch lernen, wie Sie Code mit Vererbung wiederverwenden.