Marker-Schnittstellen in Java

1. Einleitung

In diesem kurzen Tutorial lernen wir die Marker-Schnittstellen in Java kennen.

2. Marker-Schnittstellen

Eine Markierungsschnittstelle ist eine Schnittstelle, die keine Methoden oder Konstanten enthält . Es enthält Informationen zum Laufzeittyp zu Objekten , sodass der Compiler und die JVM zusätzliche Informationen zum Objekt haben .

Eine Markierungsschnittstelle wird auch als Markierungsschnittstelle bezeichnet.

Obwohl Markierungsschnittstellen immer noch verwendet werden, weisen sie sehr wahrscheinlich auf einen Codegeruch hin und sollten vorsichtig verwendet werden. Der Hauptgrund dafür ist, dass sie die Linien darüber verwischen, was eine Schnittstelle darstellt, da Markierungen kein Verhalten definieren. Neuere Entwicklungen bevorzugen Anmerkungen, um einige der gleichen Probleme zu lösen.

3. JDK-Marker-Schnittstellen

Java verfügt über viele integrierte Markierungsschnittstellen, z. B. Serializable , Cloneable und Remote.

Nehmen wir das Beispiel der klonbaren Schnittstelle. Wenn wir versuchen, ein Objekt zu klonen, das diese Schnittstelle nicht implementiert, löst die JVM eine CloneNotSupportedException aus . Daher ist die klonbare Markierungsschnittstelle ein Indikator für die JVM, dass wir die Object.clone () -Methode aufrufen können .

Auf die gleiche Weise prüft die JVM beim Aufrufen der ObjectOutputStream.writeObject () -Methode, ob das Objekt die Serializable- Marker-Schnittstelle implementiert . Wenn dies nicht der Fall ist, wird eine NotSerializableException ausgelöst. Daher wird das Objekt nicht für den Ausgabestream serialisiert.

4. Benutzerdefinierte Markierungsschnittstelle

Lassen Sie uns unsere eigene Marker-Oberfläche erstellen.

Zum Beispiel könnten wir eine Markierung erstellen, die angibt, ob ein Objekt aus der Datenbank entfernt werden kann:

public interface Deletable { }

Um eine Entität aus der Datenbank zu löschen, muss das Objekt, das diese Entität darstellt, unsere Deletable- Markierungsschnittstelle implementieren:

public class Entity implements Deletable { // implementation details }

Angenommen, wir haben ein DAO-Objekt mit einer Methode zum Entfernen von Entitäten aus der Datenbank. Wir können unsere delete () -Methode so schreiben , dass nur Objekte gelöscht werden können, die unsere Marker-Schnittstelle implementieren :

public class ShapeDao { // other dao methods public boolean delete(Object object) { if (!(object instanceof Deletable)) { return false; } // delete implementation details return true; } }

Wie wir sehen können, geben wir der JVM einen Hinweis auf das Laufzeitverhalten unserer Objekte. Wenn das Objekt unsere Markierungsschnittstelle implementiert, kann es aus der Datenbank gelöscht werden.

5. Marker-Schnittstellen vs. Anmerkungen

Durch die Einführung von Anmerkungen hat Java uns eine Alternative geboten, um die gleichen Ergebnisse wie die Markierungsschnittstellen zu erzielen. Darüber hinaus können wir wie Markierungsschnittstellen Anmerkungen auf jede Klasse anwenden und sie als Indikatoren verwenden, um bestimmte Aktionen auszuführen.

Was ist der Hauptunterschied?

Im Gegensatz zu Annotationen können wir mit Schnittstellen den Polymorphismus nutzen . Infolgedessen können wir der Markierungsschnittstelle zusätzliche Einschränkungen hinzufügen.

Fügen wir beispielsweise eine Einschränkung hinzu, dass nur ein Formtyp aus der Datenbank entfernt werden kann:

public interface Shape { double getArea(); double getCircumference(); }

In diesem Fall sieht unsere Marker-Oberfläche, nennen wir sie DeletableShape, wie folgt aus:

public interface DeletableShape extends Shape { }

Dann wird unsere Klasse die Marker-Schnittstelle implementieren:

public class Rectangle implements DeletableShape { // implementation details }

Daher sind alle DeletableShape- Implementierungen auch Shape- Implementierungen . Offensichtlich können wir das nicht mit Anmerkungen machen .

Jede Entwurfsentscheidung hat jedoch Kompromisse, und Polymorphismus kann als Gegenargument gegen Markerschnittstellen verwendet werden. In unserem Beispiel implementiert jede Klasse, die Rectangle erweitert , automatisch DeletableShape.

6. Marker-Schnittstellen im Vergleich zu typischen Schnittstellen

Im vorherigen Beispiel konnten wir dieselben Ergebnisse erzielen, indem wir die delete () -Methode unseres DAO modifizierten, um zu testen, ob unser Objekt eine Form ist oder nicht , anstatt zu testen, ob es sich um eine löschbare Datei handelt:

public class ShapeDao { // other dao methods public boolean delete(Object object) { if (!(object instanceof Shape)) { return false; } // delete implementation details return true; } }

Warum also eine Marker-Schnittstelle erstellen, wenn wir mit einer typischen Schnittstelle dieselben Ergebnisse erzielen können?

Lassen Sie sich das vorstellen, zusätzlich zu dem Form - Typ, wir entfernen möchten Person als auch Typen aus der Datenbank. In diesem Fall gibt es zwei Möglichkeiten, um dies zu erreichen:

Die erste Option besteht darin, unserer vorherigen delete () -Methode eine zusätzliche Prüfung hinzuzufügen , um zu überprüfen, ob das zu löschende Objekt eine Instanz von Person ist oder nicht.

public boolean delete(Object object) { if (!(object instanceof Shape || object instanceof Person)) { return false; } // delete implementation details return true; }

Aber was ist, wenn wir mehr Typen haben, die wir ebenfalls aus der Datenbank entfernen möchten? Dies ist natürlich keine gute Option, da wir unsere Methode für jeden neuen Typ ändern müssen .

Die zweite Option besteht darin , dass der Personentyp die Formschnittstelle implementiert , die als Markierungsschnittstelle fungiert. Aber ist ein Personenobjekt wirklich eine Form ? Die Antwort ist eindeutig nein, und das macht die zweite Option schlechter als die erste.

Obwohl wir die gleichen Ergebnisse erzielen können , wenn wir eine typische Schnittstelle als Marker verwenden, erhalten wir ein schlechtes Design.

7. Fazit

In diesem Artikel haben wir erläutert, was Markierungsschnittstellen sind und wie sie verwendet werden können. Dann haben wir uns einige integrierte Java-Beispiele für diese Art von Schnittstellen angesehen und wie sie vom JDK verwendet werden.

Als Nächstes haben wir unsere eigene Markierungsschnittstelle erstellt und diese mit einer Anmerkung abgewogen. Schließlich sehen wir, warum es in einigen Szenarien eine gute Praxis ist, eine Markierungsschnittstelle anstelle einer herkömmlichen Schnittstelle zu verwenden.

Der Code ist wie immer auf GitHub zu finden.