Ich habe gerade eine statisch verschachtelte Schnittstelle in unserer Codebasis gefunden.
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
Ich habe das noch nie gesehen. Der ursprüngliche Entwickler ist unerreichbar. Deshalb muss ich SO fragen:
Welche Semantik steckt hinter einer statischen Schnittstelle? Was würde sich ändern, wenn ich das entferne static
? Warum sollte jemand das tun?
Antworten:
Das statische Schlüsselwort im obigen Beispiel ist redundant (eine verschachtelte Schnittstelle ist automatisch "statisch") und kann ohne Auswirkung auf die Semantik entfernt werden. Ich würde empfehlen, es zu entfernen. Gleiches gilt für "public" für Schnittstellenmethoden und "public final" für Schnittstellenfelder - die Modifikatoren sind redundant und fügen dem Quellcode nur Unordnung hinzu.
In beiden Fällen deklariert der Entwickler einfach eine Schnittstelle mit dem Namen Foo.Bar. Es gibt keine weitere Zuordnung zur einschließenden Klasse, außer dass der Code, der nicht auf Foo zugreifen kann, auch nicht auf Foo.Bar zugreifen kann. (Vom Quellcode - Bytecode oder Reflection können auf Foo.Bar zugreifen, auch wenn Foo paketprivat ist!)
Es ist akzeptabel, eine verschachtelte Schnittstelle auf diese Weise zu erstellen, wenn Sie erwarten, dass sie nur von der äußeren Klasse verwendet wird, damit Sie keinen neuen Namen der obersten Ebene erstellen. Beispielsweise:
quelle
Die Frage wurde beantwortet, aber ein guter Grund für die Verwendung einer verschachtelten Schnittstelle ist, dass ihre Funktion in direktem Zusammenhang mit der Klasse steht, in der sie sich befindet. Ein gutes Beispiel hierfür ist a
Listener
. Wenn Sie eine Klasse hattenFoo
und wollten, dass andere Klassen auf Ereignisse warten können, könnten Sie eine Schnittstelle mit dem Namen deklarierenFooListener
, was in Ordnung ist, aber es wäre wahrscheinlich klarer, eine verschachtelte Schnittstelle zu deklarieren und diese anderen Klassen implementieren zu lassenFoo.Listener
( eine verschachtelte KlasseFoo.Event
ist damit nicht schlecht).quelle
java.util.Map.Entry
(eine Schnittstelle, die in einer anderen Schnittstelle verschachtelt ist).Map.Entry
) oder Klassen ebenfalls in diesem Paket enthalten sind. Ich sage das, weil ich meine Klassen gerne kurz und auf den Punkt halten möchte. Ein Leser kann auch sehen, welche anderen Entitäten mit einer Klasse verbunden sind, indem er sich die Klassen im Paket ansieht. Ich hätte wahrscheinlich ein Paketjava.collections.map
für Karten. Hier geht es um OO und Modularität.java.util
hat zu viel drin.util
ist wiecommon
- ein Geruch IMOjava.util
sicher zu viel drin. Trotzdem denke ich nicht, dass es auch ideal ist, es in so feinkörnige Pakete zu zerlegen, wie Sie es vorschlagen.java.util.MapEntry
außerhalb ihres eigenen Pakets auf. Erster Reflex: Welche Schnittstelle bezieht sich auf diese Klasse? Ich schaue in die Klasse. Sofern javadoc nicht auf diese Schnittstelle verweist, habe ich keine Ahnung von ihrer Beziehung. Außerdem sehen sich die Leute das Importpaket nicht an. Jeder hat seine eigene Meinung. Niemand hat Recht, niemand liegt falschMitgliedsschnittstellen sind implizit statisch. Der statische Modifikator in Ihrem Beispiel kann entfernt werden, ohne die Semantik des Codes zu ändern. Siehe auch die Java-Sprachspezifikation 8.5.1. Statische Elementtypdeklarationen
quelle
Eine innere Schnittstelle muss statisch sein, um darauf zugreifen zu können. Die Schnittstelle ist nicht mit Instanzen der Klasse verknüpft, sondern mit der Klasse selbst, sodass auf sie
Foo.Bar
wie folgt zugegriffen werden kann:In den meisten Fällen unterscheidet sich dies nicht von einer statischen inneren Klasse.
quelle
The interface isn't associated with instances of the class, but with the class itself
, ich habe es nicht verstandenJesses Antwort ist nah, aber ich denke, dass es einen besseren Code gibt, um zu demonstrieren, warum eine innere Schnittstelle nützlich sein kann. Schauen Sie sich den folgenden Code an, bevor Sie weiterlesen. Können Sie herausfinden, warum die innere Schnittstelle nützlich ist? Die Antwort ist, dass die Klasse DoSomethingAlready mit instanziiert werden kann, jeder Klasse kann , die A und C implementiert. nicht nur die konkrete Klasse Zoo. Dies kann natürlich auch erreicht werden, wenn AC nicht innerlich ist, aber stellen Sie sich vor, Sie verketten längere Namen (nicht nur A und C) und tun dies für andere Kombinationen (z. B. A und B, C und B usw.) und Sie leicht sehen, wie die Dinge außer Kontrolle geraten. Ganz zu schweigen davon, dass Personen, die Ihren Quellbaum überprüfen, von Schnittstellen überwältigt werden, die nur in einer Klasse von Bedeutung sind.Eine innere Schnittstelle ermöglicht die Erstellung benutzerdefinierter Typen und verbessert deren Kapselung .
quelle
Zoo
ist nicht implementieren die SchnittstelleAC
also InstanzenZoo
können nicht an den Konstruktor übergeben werden , vonDoSomethingAlready
denen erwartetAC
. Die Tatsache, dassAC
beideA
und erweitert werdenC
, bedeutet nicht, dass Klassen implementierenA
und aufC
magische Weise auch implementierenAC
.Um Ihre Frage sehr direkt zu beantworten, schauen Sie sich Map.Entry an.
Map.Entry
Auch dies kann nützlich sein
Blogeintrag für statisch verschachtelte Inerfaces
quelle
Normalerweise sehe ich statische innere Klassen. Statische innere Klassen können nicht auf die enthaltenen Klassen verweisen, wohingegen nicht statische Klassen dies können. Es sei denn, Sie stoßen auf Paketkollisionen (es gibt bereits eine Schnittstelle namens Bar im selben Paket wie Foo). Ich denke, ich würde es zu einer eigenen Datei machen. Es könnte auch eine Entwurfsentscheidung sein, die logische Verbindung zwischen Foo und Bar durchzusetzen. Vielleicht wollte der Autor, dass Bar nur mit Foo verwendet wird (obwohl eine statische innere Schnittstelle dies nicht erzwingt, sondern nur eine logische Verbindung).
quelle
Wenn Sie die Klasse Foo in die Schnittstelle Foo ändern, ist das Schlüsselwort "public" im obigen Beispiel ebenfalls redundant, da
quelle
1998 schlug Philip Wadler einen Unterschied zwischen statischen und nicht statischen Schnittstellen vor.
Zum Beispiel schlug er eine Lösung für das Ausdrucksproblem vor , bei der es sich um die Nichtübereinstimmung zwischen dem Ausdruck "wie viel kann Ihre Sprache ausdrücken" einerseits und dem Ausdruck "die Begriffe, die Sie in Ihrer Sprache darstellen möchten" andererseits handelt .
Ein Beispiel für den Unterschied zwischen statischen und nicht statischen verschachtelten Schnittstellen ist in seinem Beispielcode zu sehen :
Sein Vorschlag hat es in Java 1.5.0 nie geschafft. Daher sind alle anderen Antworten richtig: Es gibt keinen Unterschied zu statischen und nicht statischen verschachtelten Schnittstellen.
quelle
In Java ermöglicht die statische Schnittstelle / Klasse, dass die Schnittstelle / Klasse wie eine Klasse der obersten Ebene verwendet wird, dh von anderen Klassen deklariert werden kann. Sie können also Folgendes tun:
Ohne die statische Aufladung würde das oben Gesagte nicht kompiliert werden können. Dies hat den Vorteil, dass Sie keine neue Quelldatei benötigen, um die Schnittstelle zu deklarieren. Es ordnet die Schnittstellenleiste auch visuell der Klasse Foo zu, da Sie Foo.Bar schreiben müssen, und impliziert, dass die Foo-Klasse etwas mit Instanzen von Foo.Bar tut.
Eine Beschreibung der Klassentypen in Java .
quelle
Statisch bedeutet, dass jeder Klassenteil des Pakets (Projekts) ohne Verwendung eines Zeigers darauf zugreifen kann. Dies kann je nach Situation nützlich oder hinderlich sein.
Das perfekte Beispiel für die Nützlichkeit "statischer" Methoden ist die Math-Klasse. Alle Methoden in Mathe sind statisch. Dies bedeutet, dass Sie nicht aus dem Weg gehen, eine neue Instanz erstellen, Variablen deklarieren und in noch mehr Variablen speichern müssen. Sie können einfach Ihre Daten eingeben und ein Ergebnis erhalten.
Statik ist nicht immer so nützlich. Wenn Sie beispielsweise einen Fallvergleich durchführen, möchten Sie Daten möglicherweise auf verschiedene Arten speichern. Sie können nicht drei statische Methoden mit identischen Signaturen erstellen. Sie benötigen 3 verschiedene Instanzen, nicht statisch, und dann können Sie vergleichen, denn wenn es statisch ist, ändern sich die Daten nicht zusammen mit der Eingabe.
Statische Methoden eignen sich für einmalige Rückgaben und schnelle Berechnungen oder einfach zu ermittelnde Daten.
quelle