web-dev-qa-db-ger.com

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

Ich versuche nur zu verstehen, warum alle in einer Schnittstelle definierten Felder implizit static und final sind. Die Idee, Felder static beizubehalten, ist 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 static und final erstellt haben?

90
peakit

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

BTW: Eine Konstante in Java wird durch ein statisches abschließendes Feld definiert (und der Name verwendet per Konvention UPPER_CASE_AND_UNDERSCORES).

119
Adriaan Koster

GRUND FÜR SEIN final

Alle 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 FÜR SEIN static

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

24

Es gibt ein paar Punkte, die hier übersehen werden:

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

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

(Beachten Sie, dass dies in einer Anmerkungsdefinition javac verwirren sein kann, was sich auf die Tatsache bezieht, dass sich das Obige tatsächlich zu einem statischen Initialisierer kompiliert.

Auch der Grund für diese Einschränkung ist eher stilistisch als technisch, und viele Leute würden gerne entspannt sehen .

16
Jesse Glick

Die Felder müssen statisch sein, da sie nicht abstrakt sein können (wie bei 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 die Felder möglicherweise von vielen verschiedenen Implementierern aufgerufen werden können. Auch um zu vermeiden, dass es erneut implementiert wird (versteckt).

Nur mein Gedanke.

9
NawaMan

Die Anforderung, dass die Felder als endgültig gelten, halte ich für unangemessen restriktiv und für einen Fehler der Java-Designer. Es gibt Zeiten, z. Tree-Handling, wenn Sie Konstanten in der Implementierung festlegen müssen, die zum Ausführen von Operationen an einem Objekt des Schnittstellentyps erforderlich sind. Die Auswahl eines Codepfads für die implementierende Klasse ist ein Klick. Die Problemumgehung, die ich verwende, besteht darin, eine Schnittstellenfunktion zu definieren und diese 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 eine abweichende Implementierung, 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";
    ...
}
2
Carl Klapper

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, das nicht endgültige Schnittstellenfeld in allen Klassen, die diese Schnittstelle erweitern, mit dem gleichen Offset zu versehen. Daher müssen unterschiedliche Mechanismen für den Feldzugriff implementiert werden: zwei Speicherzugriffe (Feldversatz abrufen, Feldwert abrufen) anstelle von einem plus Art der virtuellen Feldtabelle (analog zur virtuellen Methodentabelle). Vermutlich wollten sie jvm einfach nicht mit einer Funktionalität erschweren, die mit vorhandenen Methoden (Methoden) einfach simuliert werden kann.

In scala können wir Felder in Schnittstellen haben, obwohl sie intern wie oben beschrieben (als Methoden) implementiert sind.

0
Yaroslav