Mir wurde beigebracht, dass die Marker-Schnittstelle in Java eine leere Schnittstelle ist und dem Compiler oder der JVM signalisiert, dass die Objekte der Klasse, die diese Schnittstelle implementieren, auf besondere Weise behandelt werden müssen, z. B. Serialisieren, Klonen usw.
Aber in letzter Zeit habe ich gelernt, dass es eigentlich nichts mit dem Compiler oder der JVM zu tun hat. Zum Beispiel im Fall der Serializable
Schnittstelle der Methode writeObject(Object)
der ObjectOutputStream
tut , wie etwas instanceOf Serializable
zu erkennen , ob die Klasse implementiert Serializable
und führt NotSerializableException
entsprechend. Alles wird im Code behandelt und dies scheint ein Entwurfsmuster zu sein, so dass wir meiner Meinung nach unsere eigenen Markierungsschnittstellen definieren können.
Nun meine Zweifel:
Ist die oben im 1. Punkt erwähnte Definition einer Marker-Schnittstelle falsch? Wie können wir dann eine Marker-Schnittstelle definieren?
Und anstatt den
instanceOf
Operator zu verwenden, warum kann die Methode nichtwriteObject(Serializable)
so sein, dass eine Typprüfung zur Kompilierungszeit statt zur Laufzeit erfolgt?Wie sind Anmerkungen besser als Markierungsschnittstellen?
quelle
Serializable
als Annotation ist Unsinn und@NonNull
als Schnittstelle ist Unsinn. Ich würde sagen: Anmerkungen sind Marker + Metadaten. Übrigens: Forefunner of Annotations war XDoclet, geboren in Javadoc, getötet von Annotations.Antworten:
writeObject(Serializable)
so sein, dass eine Typprüfung zur Kompilierungszeit erfolgt. Auf diese Weise können Sie vermeiden, dass Ihr Code mit dem Namen der Markierungsschnittstelle verschmutzt wird, wenn eine "EbeneObject
" benötigt wird. Wenn Sie beispielsweise eine Klasse erstellen, die serialisierbar sein muss und über Objektelemente verfügt, müssen SieSerializable
beim Kompilieren entweder Casting durchführen oder Ihre Objekte erstellen. Dies ist unpraktisch, da die Schnittstelle keine Funktionalität aufweist.quelle
writeObject
privat ist, bedeutet das, dass zum Beispiel eine Klasse nicht die Implementierung der Superklasse aufrufen mussCloneable
ist nicht klar, ob es sich um eine Bibliothek oder eine JVM-Behandlung der Instanz handelt, die geändert wird.Es ist nicht möglich zu erzwingen
Serializable
auf ,writeObject
weil Kinder nicht serialisierbaren Klasse serialisierbar sein können, aber ihre Instanzen upcasted zurück auf die Elternklasse sein kann. Infolgedessen bedeutet das Halten eines Verweises auf etwas nicht serialisierbares (wieObject
) nicht, dass die referenzierte Instanz nicht wirklich serialisiert werden kann. Zum Beispiel inDie übergeordnete Klasse (
Object
) ist nicht serialisierbar und würde mit ihrem parameterlosen Konstruktor initialisiert. Der Wert, auf den von ,, verwiesen wirdx
,String
ist serialisierbar und die bedingte Anweisung würde ausgeführt.quelle
Das Obige begann als Kopie eines Blogposts , wurde jedoch für die Grammatik leicht bearbeitet.
quelle
Eine / A-Markierungsschnittstelle, wie der Name schon sagt , existiert nur, um alles, was darüber weiß, darüber zu informieren , dass eine Klasse etwas deklariert. Das alles kann die JDK-Klasse für die
Serializable
Schnittstelle sein oder jede Klasse, die Sie selbst für eine benutzerdefinierte schreiben.b / Wenn es sich um eine Markierungsschnittstelle handelt, sollte dies nicht die Existenz einer Methode implizieren. Es ist besser, die implizierte Methode in die Schnittstelle aufzunehmen. Sie können es jedoch nach Ihren Wünschen gestalten, wenn Sie wissen, warum Sie es benötigen
c / Es gibt kaum einen Unterschied zwischen einer leeren Schnittstelle und einer Anmerkung, die keinen Wert oder Parameter verwendet. Der Unterschied besteht jedoch darin, dass eine Anmerkung eine Liste von Schlüsseln / Werten deklarieren kann, auf die zur Laufzeit zugegriffen werden kann.
quelle
Ich habe eine einfache Demonstration gemacht, um Zweifel Nr. 1 und 2 zu lösen:
Wir werden eine bewegliche Schnittstelle haben, die von
MobilePhone.java
Class implementiert wird, und eine weitere KlasseLandlinePhone.java
, die KEINE bewegliche Schnittstelle implementiertUnsere Marker-Oberfläche:
LandLinePhone.java
undMobilePhone.java
Unsere benutzerdefinierte Ausnahmeklasse: package com;
Unsere Testklasse:
TestMArkerInterface.java
Wenn wir nun die Hauptklasse ausführen:
Unabhängig davon, welche Klasse die Markierungsschnittstelle implementiert, besteht
Movable
sie den Test. Andernfalls wird eine Fehlermeldung angezeigt.Auf diese Weise wird die
instanceOf
Bedienerprüfung auf Serializable , Cloneable usw. Durchgeführtquelle
ein. Ich habe sie immer als Designmuster gesehen und nichts JVM-Special Ich habe dieses Muster in verschiedenen Situationen verwendet.
c. Ich glaube, dass die Verwendung von Anmerkungen zum Markieren von etwas eine bessere Lösung ist als die Verwendung von Markierungsschnittstellen. Einfach, weil Schnittstellen in erster Linie darauf abzielen, gemeinsame Schnittstellen von Typen / Klassen zu definieren. Sie sind Teil der Klassenhierarchie.
Anmerkungen zielen darauf ab, Code-Informationen für Code bereitzustellen, und ich denke, dass Marker Meta-Informationen sind. Sie sind also genau für diesen Anwendungsfall.
quelle
Es hat (notwendigerweise) nichts mit der JVM und den Compilern zu tun, es hat etwas mit jedem Code zu tun, der an einer bestimmten Markierungsschnittstelle interessiert ist und diese testet.
Es ist eine Designentscheidung und das aus gutem Grund. Siehe die Antwort von Audrius Meškauskas.
In Bezug auf dieses spezielle Thema denke ich nicht, dass es darum geht, besser oder schlechter zu sein. Die Marker-Oberfläche macht genau das, was sie soll.
quelle
Der Hauptzweck von Markierungsschnittstellen besteht darin, spezielle Typen zu erstellen, bei denen die Typen selbst kein eigenes Verhalten aufweisen.
Hier stellt die Speichermethode sicher, dass nur die Objekte von Klassen gespeichert werden, die die MarkerEntity-Schnittstelle implementieren, für andere Typen wird InvalidEntityFoundException ausgelöst. Hier definiert die MarkerEntity-Markerschnittstelle einen Typ, der den Klassen, die ihn implementieren, ein besonderes Verhalten hinzufügt.
Obwohl Annotationen jetzt auch zum Markieren von Klassen für einige spezielle Behandlungen verwendet werden können, ersetzen Markierungsanmerkungen das Namensmuster und nicht die Markierungsschnittstellen.
Markierungsanmerkungen können die Markierungsschnittstellen jedoch nicht vollständig ersetzen, da: Markierungsschnittstellen werden verwendet, um den Typ zu definieren (wie oben bereits erläutert), während dies bei Markierungsanmerkungen nicht der Fall ist.
Quelle für Kommentar zur Markierungsschnittstelle
quelle
Ich würde zunächst einmal argumentieren, dass Serializable und Cloneable schlechte Beispiele für Marker-Interfaces sind. Sicher, sie sind Schnittstellen zu Methoden, aber sie implizieren Methoden wie
writeObject(ObjectOutputStream)
. (Der Compiler erstellt einewriteObject(ObjectOutputStream)
Methode für Sie, wenn Sie sie nicht überschreiben, und alle Objekte haben sie bereitsclone()
, aber der Compiler erstellt erneut eine echteclone()
Methode für Sie, jedoch mit Einschränkungen. Beides sind seltsame Randfälle, die es wirklich nicht sind gute Designbeispiele.)Marker-Schnittstellen werden im Allgemeinen für einen von zwei Zwecken verwendet:
1) Als Abkürzung, um einen zu langen Typ zu vermeiden, der bei vielen Generika auftreten kann. Angenommen, Sie haben diese Methodensignatur:
Das ist chaotisch und nervig zu tippen und vor allem schwer zu verstehen. Betrachten Sie stattdessen Folgendes:
Dann sieht Ihre Methode folgendermaßen aus:
Es ist nicht nur klarer, sondern Sie können jetzt die Widget-Oberfläche mit Javadoc bearbeiten, und es ist auch einfacher, nach allen Vorkommen in Ihrem Widget-Code zu suchen.
2) Marker-Schnittstellen können auch verwendet werden, um das Fehlen von Schnittpunkttypen in Java zu umgehen. Bei einer Markierungsschnittstelle können zwei verschiedene Typen erforderlich sein, z. B. eine Methodensignatur. Angenommen, Sie haben ein Schnittstellen-Widget in Ihrer Anwendung, wie oben beschrieben. Wenn Sie eine Methode haben, für die ein Widget erforderlich ist, mit dem Sie auch darüber iterieren können (es ist erfunden, aber arbeiten Sie hier mit mir zusammen), besteht Ihre einzige gute Lösung darin, eine Markierungsschnittstelle zu erstellen, die beide Schnittstellen erweitert:
Und in Ihrem Code:
quelle
Serializable
oderCloneable
. Sie können dies überprüfen, indem Sie Ihre Klassendateien überprüfen. Darüber hinaus geht es beim Erstellen von „Shortcut-Schnittstellen“ nicht um Marker-Schnittstellen. Und es ist eine wirklich schlechte Codierungspraxis, da zusätzliche Implementierungsklassen erstellt werden müssten , um die zusätzlichen Schnittstellen zu erfüllen. Java hat übrigens seit einem Jahrzehnt Schnittpunkttypen. Erfahren Sie mehr über Generika…Wenn eine Schnittstelle keine Methode enthält und durch Implementierung dieser Schnittstelle, wenn unser Objekt eine bestimmte Fähigkeit erhält, werden solche Schnittstellentypen als Markierungsschnittstellen bezeichnet.
quelle