Warum sind alle Felder in einer Schnittstelle implizit statisch und endgültig?

100

Ich versuche nur zu verstehen, warum alle in einer Schnittstelle definierten Felder implizit staticund implizit sind final. Die Idee, Felder zu behalten, staticist für mich sinnvoll, da Sie keine Objekte einer Schnittstelle haben können, aber warum sind sie final(implizit)?

Weiß jemand, warum Java-Designer die Felder in einer Schnittstelle erstellt haben staticund final?

Peakit
quelle
Für einen Hinweis für mich: Es ist statisch, weil die Felder der Schnittstelle nicht Teil des Objekts werden, das es implementiert.
Raining

Antworten:

126

Eine Schnittstelle kann kein Verhalten oder keinen Status haben, da nur ein Interaktionsvertrag und keine Implementierungsdetails angegeben werden sollen. 'Kein Verhalten' wird erzwungen, indem Methoden- / Konstruktorkörper oder statische / Instanzinitialisierungsblöcke nicht zugelassen werden. 'Kein Status' wird erzwungen, indem nur statische Endfelder zugelassen werden. Daher kann die Klasse einen Status (statischen Status) haben, aber der Instanzstatus wird von der Schnittstelle nicht abgeleitet.

Übrigens: Eine Konstante in Java wird durch ein statisches Endfeld definiert (und gemäß Konvention verwendet der Name UPPER_CASE_AND_UNDERSCORES).

Adriaan Koster
quelle
54
Es ist nicht unbedingt wahr, dass Endfelder Konstanten sind; Das ist nur für primitive Typen garantiert. Im Allgemeinen bedeutet das letzte Schlüsselwort lediglich, dass sich der Speicherort nicht ändert.
Pops
8
Ich habe nicht gesagt, dass Endfelder Konstanten sind, nur dass Konstanten Endfelder sind. Beachten Sie, dass ein nicht primitives statisches Endfeld in eine Schnittstelle eingefügt werden darf. Auch wenn sich der Inhalt dieses Feldes ändern kann, ist der Verweis darauf konstant.
Adriaan Koster
1
@AdriaanKoster Sie haben genau gesagt, dass das letzte Feld konstant ist: Kein Status wird erzwungen, indem nur Konstanten zugelassen werden. - Dieser Satz impliziert, dass alle letzten Felder konstant sind. Sie könnten versuchen, weiter über die von Ihnen verwendeten Wörter zu streiten, aber offensichtlich ist Ihre Aussage zumindest irreführend.
Tomáš Zato - Wiedereinsetzung Monica
2
Es muss mein schwindender Intellekt sein, aber nach sechs Jahren des Betrachtens dieser Antwort, die zufällig meine Antwort mit der höchsten Punktzahl ist, verstehe ich die Bemerkungen immer noch nicht. Bitte schlagen Sie einen anderen Wortlaut vor, da ich nichts falsch sehen kann.
Adriaan Koster
Es war möglicherweise die Absicht der Java-Designer, eine Schnittstelle zustandslos zu machen, aber sie sind fehlgeschlagen, weil ein Instanzfeld eine modifizierbare Klasse sein kann. Anstatt zuzugeben, dass sie fehlgeschlagen sind, erzwingen sie, Instanzfelder zu erzwingen static final, was so real (real ist C / C ++) ist, constwie Sie es in Java bekommen können. Leider ist dies implizit und kann für den Nichtfachmann zu Verwirrung führen. (Ich habe gerade festgestellt, dass dies der Fall ist, staticweil ich unbeabsichtigtes Verhalten beobachtet habe. Ich habe erfahren, dass sie finalnur aus dieser Antwort stammen.)
Nicht-Benutzer
27

Grund zu sein final

Implementierungen können den Wert von Feldern ändern, wenn sie nicht als endgültig definiert sind. Dann würden sie Teil der Implementierung werden. Eine Schnittstelle ist eine reine Spezifikation ohne Implementierung.

Grund zu sein static

Wenn sie statisch sind, gehören sie zur Schnittstelle und nicht zum Objekt oder zum Laufzeittyp des Objekts.

Gurpreet singh sidhuu
quelle
18

Hier werden einige Punkte beschönigt:

Nur weil Felder in einer Schnittstelle implizit statisch final sind, bedeutet dies nicht, dass sie Konstanten zur Kompilierungszeit oder sogar unveränderlich sein müssen. Sie können zB definieren

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(Beachten Sie, dass dies innerhalb einer Annotationsdefinition zu einer Verwirrung von javac führen kann, da das oben Gesagte tatsächlich zu einem statischen Initialisierer kompiliert wird.)

Der Grund für diese Einschränkung ist eher stilistisch als technisch, und viele Leute möchten , dass sie entspannt ist .

Jesse Glick
quelle
9

Die Felder müssen statisch sein, da sie nicht abstrakt sein können (wie Methoden). Da sie nicht abstrakt sein können, können die Implementierer die unterschiedliche Implementierung der Felder nicht logisch bereitstellen.

Ich denke, die Felder müssen endgültig sein, da auf die Felder möglicherweise von vielen verschiedenen Implementierern zugegriffen wird und sie möglicherweise geändert werden können. Dies kann problematisch sein (da die Synchronisation). Auch um zu vermeiden, dass es erneut implementiert wird (versteckt).

Nur mein Gedanke.

NawaMan
quelle
NawMan, Ihre Erklärung zu "Die Felder müssen statisch sein ..." macht wenig Sinn. Aber Sie hatten sehr Recht mit dem "Die Felder müssen endgültig sein ..."
Höhepunkt
1
Ich glaube nicht, dass er Recht hat, warum die Felder endgültig sein müssen. Es ist nicht problematisch, verschiedenen Implementierern zu erlauben, ein Feld zu ändern, da sonst die Vererbung problematisch wäre. Felder müssen endgültig sein, wie Adriaan sagte, da eine Schnittstelle zustandslos ist und sein sollte. Eine Schnittstelle mit einem Zustand sollte grundsätzlich eine abstrakte Klasse sein.
Axelle Ziegler
Wenn Sie ein public staticFeld haben, das nicht ist final, werden sich Findbugs beschweren (zu Recht!).
Tom Hawtin - Tackline
2

Ich betrachte die Anforderung, dass die Felder endgültig sein müssen, als unangemessen restriktiv und als Fehler der Java-Sprachdesigner. Es gibt Zeiten, z. B. die Baumbehandlung, in denen Sie Konstanten in der Implementierung festlegen müssen, die zum Ausführen von Operationen an einem Objekt des Schnittstellentyps erforderlich sind. Das Auswählen eines Codepfads in der implementierenden Klasse ist ein Problem. Die Problemumgehung, die ich verwende, besteht darin, eine Schnittstellenfunktion zu definieren und sie durch Rückgabe eines Literal zu implementieren:

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

Es wäre jedoch einfacher, klarer und weniger anfällig für fehlerhafte Implementierungen, diese Syntax zu verwenden:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}
Carl Klapper
quelle
Sie scheinen sich mehr darüber zu beschweren, dass die Felder statisch als endgültig sind.
Daniel Yankowsky
0

Spezifikation, Verträge ... Die Maschinenanweisung für den Feldzugriff verwendet die Objektadresse plus Feldversatz. Da Klassen viele Schnittstellen implementieren können, gibt es keine Möglichkeit, ein nicht endgültiges Schnittstellenfeld so zu gestalten, dass es in allen Klassen, die diese Schnittstelle erweitern, denselben Offset aufweist. Daher muss ein anderer Mechanismus für den Feldzugriff implementiert werden: zwei Speicherzugriffe (Feldversatz abrufen, Feldwert abrufen) anstelle von einem plus Beibehaltung einer virtuellen Feldtabelle (analog zur virtuellen Methodentabelle). Vermutlich wollten sie jvm nicht für Funktionen komplizieren, die einfach über vorhandene Methoden simuliert werden können.

In Scala können wir Felder in Schnittstellen haben, obwohl sie intern wie oben erläutert implementiert sind (als Methoden).

Jaroslaw
quelle
-1

static::

Alles , was (variable oder Methode) , das ist staticin Java kann aufgerufen werden , Classname.variablenameoder Classname.methodnameoder direkt. Es ist nicht obligatorisch, es nur unter Verwendung des Objektnamens aufzurufen.

In der Schnittstelle können Objekte nicht deklariert werden und staticermöglichen das Aufrufen von Variablen nur über den Klassennamen, ohne dass ein Objektname erforderlich ist.

final::

Es hilft, einen konstanten Wert für eine Variable beizubehalten, da sie in ihren Unterklassen nicht überschrieben werden kann.

Sabika
quelle