Warum sind Schnittstellenvariablen standardmäßig statisch und endgültig?


273

Warum sind Schnittstellenvariablen in Java standardmäßig statisch und endgültig?


41
Sie sollten keine Variablen in Interfaces einfügen.
Cherouvim

34
Weil Schnittstellen Verträge definieren, die auf verschiedene Arten implementiert werden können. Der Wert einer Variablen ist die Implementierung.
Cherouvim

10
Wir können sicherlich, wenn wir wissen, dass alle Klassen, die die Schnittstelle implementieren, einige konstante Variablen haben (z. B. Feldnamen).
Aniket Thakur

Ist es eine gute Idee, eine Variable in einer Klasse zu einer Instanz der Schnittstelle zu machen, die die Klasse implementiert? Ich habe das schon mal gehört.
Doug Hauf

Schnittstellen in Java folgen dem ACID-Prinzip, endgültig aufgrund der Normalisierung in C. @cherouvim Der Typ einer Variablen ist die Implementierung, eine Variable muss mit oder ohne Wert deklariert werden und die Definition einer Variablen ist der Wert. Wenn Sie den Wert einer Variablen ändern, wird diese nicht neu implementiert, sondern neu definiert.
Grim

Antworten:


263

Aus den FAQ zum Java-Interface-Design von Philip Shaw:

Schnittstellenvariablen sind statisch, da Java-Schnittstellen nicht eigenständig instanziiert werden können. Der Wert der Variablen muss in einem statischen Kontext zugewiesen werden, in dem keine Instanz vorhanden ist. Der letzte Modifikator stellt sicher, dass der der Schnittstellenvariablen zugewiesene Wert eine echte Konstante ist, die vom Programmcode nicht neu zugewiesen werden kann.

Quelle


39
Beachten Sie, dass abstrakte Klassen auch nicht "eigenständig" instanziiert werden können und dass diese Instanzvariablen haben können.
Macias

18
Diese Erklärung für den staticModifikator ist völlig falsch. Die öffentlichen Instanzvariablen einer Klasse sind Teil ihrer Schnittstelle, und es gibt keinen Grund, warum sie nicht interfacewie Instanzmethoden in Java abstrahiert werden sollten. Es spielt keine Rolle, dass ein Java interfacenicht direkt instanziiert werden kann - Sie können immer noch Instanzen von Klassen haben, die das implementieren, interfaceund es ist sinnvoll zu verlangen, dass sie eine bestimmte öffentliche Instanzvariable haben. Der Teil über finalbietet überhaupt keine Erklärung - er beschreibt nur, was finalbedeutet.
Pyrocrasty

3
Das obige Zitat ist im Kontext besser. Der Grund dafür ist, dass "Schnittstellenvariablen Java-Konstanten sein sollen". Das Zitat ging nur darauf ein, warum eine solche Konstante statisch und endgültig sein würde. Das stimmt, aber die eigentliche Frage ist: Warum sind Variablen nicht als Teil der eigentlichen Schnittstelle zulässig (dh Angabe der Namen und Typen nicht privater Mitglieder, die in einer implementierenden Klasse vorkommen müssen). Wenn sie spezielle "Schnittstellenkonstanten" wollten, hätten sie eine neue Syntax verwenden oder einfach entscheiden können, dass alle tatsächlich in einer Schnittstelle definierten Variablen Schnittstellenkonstanten sind.
Pyrocrasty

6
Schnittstellen können keine Instanzvariablen haben, um eine mehrfache Vererbung von Statusproblemen zu vermeiden. Siehe docs.oracle.com/javase/tutorial/java/IandI/… . Eine Klasse kann aus demselben Grund nicht mehr als eine Klasse erweitern.
Denis

1
Wie werden Standardmethoden eingeführt und sie haben eine Instanz, doch die Instanzvariable wird nicht unterstützt ...
M.kazem Akhgary

41

Da die Schnittstelle kein direktes Objekt hat, besteht die einzige Möglichkeit, auf sie zuzugreifen, in der Verwendung einer Klasse / Schnittstelle. Wenn daher eine Schnittstellenvariable vorhanden ist, sollte diese statisch sein, da sie sonst für die Außenwelt überhaupt nicht zugänglich ist. Jetzt, da es statisch ist, kann es nur einen Wert enthalten, und alle Klassen, die es implementieren, können ihn ändern, und daher wird alles durcheinander sein.

Wenn es also überhaupt eine Schnittstellenvariable gibt, ist diese implizit statisch, endgültig und offensichtlich öffentlich !!!


Natürlich wäre eine Instanzvariable zugänglich, wenn sie in Java erlaubt wäre interface. Eine Klasse würde die Schnittstelle implementieren und die Instanzvariable deklarieren (wie von der Schnittstelle gefordert). Sein Konstruktor (oder eine andere Methode) legt die Instanzvariable fest. Wenn eine Instanz der Klasse instanziiert wird, können Sie auf ihre Instanzvariable zugreifen.
Pyrocrasty

Java ermöglicht statische Methoden mit Körpern in einer Schnittstelle. Diese könnten auf die statischen Variablen zugreifen. Sie können sie einfach nicht ändern, was bedeutet, dass die statischen Funktionen keine Daten speichern können
simpleuser

36

public : für die Zugänglichkeit über alle Klassen hinweg, genau wie die in der Schnittstelle vorhandenen Methoden

statisch : Da die Schnittstelle kein Objekt haben kann, kann der Name interfaceName.variableName verwendet werden, um darauf zu verweisen, oder direkt der variableName in der Klasse, die ihn implementiert.

final : um sie zu Konstanten zu machen. Wenn zwei Klassen dieselbe Schnittstelle implementieren und Sie beiden das Recht geben, den Wert zu ändern, tritt ein Konflikt im aktuellen Wert der Variable auf, weshalb nur eine einmalige Initialisierung zulässig ist.

Außerdem sind alle diese Modifikatoren für eine Schnittstelle implizit, Sie müssen keine wirklich angeben.


15

( Dies ist keine philosophische, sondern eher eine praktische Antwort ). Das Erfordernis eines staticModifikators ist offensichtlich, was von anderen beantwortet wurde. Da die Schnittstellen nicht instanziiert werden können, besteht die einzige Möglichkeit, auf ihre Felder zuzugreifen, darin, sie zu einem Klassenfeld zu machen static.

Der Grund dafür, dass die interfaceFelder automatisch final(konstant) werden, besteht darin, zu verhindern, dass verschiedene Implementierungen versehentlich den Wert der Schnittstellenvariablen ändern, was sich versehentlich auf das Verhalten der anderen Implementierungen auswirken kann. Stellen Sie sich das folgende Szenario vor, in dem eine interfaceEigenschaft nicht explizit finalvon Java übernommen wurde:

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

Stellen Sie sich nun vor, was passieren würde, wenn eine andere Klasse, die implementiert, Actionableden Status der Schnittstellenvariablen ändert:

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

Wenn diese Klassen von einem Klassenladeprogramm in einer einzelnen JVM geladen werden, kann das Verhalten von NuclearActionvon einer anderen Klasse beeinflusst werden CleanAction, wenn sie performAction()aufgerufen wird, nachdem sie CleanActionausgeführt wurde (im selben Thread oder auf andere Weise), was in diesem Fall katastrophal sein kann (semantisch also).

Da wir nicht wissen, wie jede Implementierung von a interfacediese Variablen verwenden wird, müssen sie implizit sein final.


9

Weil alles andere Teil der Implementierung ist und Schnittstellen keine Implementierung enthalten können.


1
Was ist dann der Grund für das Finale?
Jothi

7
Um anzuzeigen, dass es eine Konstante ist. Java hat kein const-Schlüsselwort. Mit static final deklarieren Sie Konstanten.
Amir Afghani

5
Seit Java 8 können sie eine Implementierung enthalten. Es wird jedoch dringend empfohlen, diese nicht zu verwenden, wenn Sie keine Backwarts-Kompatibilität benötigen. :)
Codepleb

6
public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

Hier ist die Lösung.

System.out.println(A.x); // done

Ich denke, es ist der einzige Grund, warum Schnittstellenvariablen statisch sind.

Deklarieren Sie keine Variablen innerhalb der Schnittstelle.


3
In der Tat würde es ohne die Spezifikation "Axe" nicht einmal kompilieren ", so dass es tatsächlich sicher ist, Variablen (die implizit öffentlich statisch endgültig sind) in Schnittstellen zu verwenden
Marco

Ich bin mit der Antwort nicht einverstanden, da @Marco sagte, dass sie nicht einmal kompiliert werden würde. Ich habe bisher keinen anderen Nachteil gefunden, vielleicht nur, dass Sie nicht static finalvor der Variablen geschrieben sehen, die tatsächlich statisch und endgültig ist.
Micer

5

statisch - weil die Schnittstelle keine Instanz haben kann. und schließlich - weil wir es nicht ändern müssen.


15
"wir brauchen nicht" == "wir sind nicht erlaubt", mischen Sie nicht die Bedeutungen.
Peter - Wiedereinstellung Monica

3

weil:

Static : Da wir keine Objekte von Schnittstellen haben können, sollten wir die Verwendung von Mitgliedsvariablen auf Objektebene vermeiden und Variablen auf Klassenebene verwenden, dh statisch.

Final : damit wir keine mehrdeutigen Werte für die Variablen haben (Diamond-Problem - Multiple Inheritance).

Und laut Dokumentationsschnittstelle handelt es sich um einen Vertrag und nicht um eine Implementierung.

Referenz: Abhishek Jains Antwort auf Quora


2

Java erlaubt keine abstrakten Variablen und / oder Konstruktordefinitionen in Schnittstellen. Lösung: Hängen Sie einfach eine abstrakte Klasse zwischen Ihre Schnittstelle und Ihre Implementierung, wodurch die abstrakte Klasse nur folgendermaßen erweitert wird:

 public interface IMyClass {

     void methodA();
     String methodB();
     Integer methodC();

 }

 public abstract class myAbstractClass implements IMyClass {
     protected String varA, varB;

     //Constructor
     myAbstractClass(String varA, String varB) {
         this.varA = varA;
         this.varB = VarB;
     }

     //Implement (some) interface methods here or leave them for the concrete class
     protected void methodA() {
         //Do something
     }

     //Add additional methods here which must be implemented in the concrete class
     protected abstract Long methodD();

     //Write some completely new methods which can be used by all subclasses
     protected Float methodE() {
         return 42.0;
     }

 }

 public class myConcreteClass extends myAbstractClass {

     //Constructor must now be implemented!
     myClass(String varA, String varB) {
         super(varA, varB);
     }

     //All non-private variables from the abstract class are available here
     //All methods not implemented in the abstract class must be implemented here

 }

Sie können eine abstrakte Klasse auch ohne Schnittstelle verwenden, wenn Sie sicher sind, dass Sie sie später nicht zusammen mit anderen Schnittstellen implementieren möchten. Bitte beachten Sie, dass Sie keine Instanz einer abstrakten Klasse erstellen können. Sie MÜSSEN diese zuerst erweitern.

(Das Schlüsselwort "protected" bedeutet, dass nur erweiterte Klassen auf diese Methoden und Variablen zugreifen können.)

Spyro


1

Eine Schnittstelle ist ein Vertrag zwischen zwei Parteien, der unveränderlich, in den Stein gemeißelt und somit endgültig ist. Siehe Design by Contract .


1

Schnittstelle: Systemanforderungsdienst.

In der Schnittstelle werden Variablen standardmäßig durch einen öffentlichen, statischen, endgültigen Zugriffsmodifikator zugewiesen. Weil :

public: Es kann vorkommen, dass die Schnittstelle in einem anderen Paket platziert wird. Es muss also von überall im Projekt auf die Variable zugreifen.

statisch: Als solche kann eine unvollständige Klasse kein Objekt erstellen. Im Projekt müssen wir also auf die Variable ohne Objekt zugreifen, damit wir mit Hilfe von zugreifen könneninterface_filename.variable_name

final: Angenommen, eine Schnittstelle wird von vielen Klassen implementiert und alle Klassen versuchen, auf die Schnittstellenvariable zuzugreifen und diese zu aktualisieren. Dies führt zu inkonsistenten Datenänderungen und wirkt sich auf jede andere Klasse aus. Daher muss der Zugriffsmodifikator mit final deklariert werden.


0

In der JavaSchnittstelle können Sie keine Instanzvariablen deklarieren. Die Verwendung einer in einer Schnittstelle deklarierten Variablen als Instanzvariable gibt einen Fehler bei der Kompilierung zurück.

Sie können eine konstante Variable deklarieren, static finaldie sich von einer Instanzvariablen unterscheidet.


Das ist einfach falsch. Der Compiler wird sich nur beschweren, wenn Sie ihn privat oder geschützt machen. Unter der Haube werden sie, wie andere bereits erwähnt haben, in ein öffentliches statisches Finale umgewandelt. Und ich denke, es ist ziemlich offensichtlich, warum. Weil die Schnittstelle das Verhalten bestimmen soll, nicht den Status.
Mikayil Abdullayev

0

Die Schnittstelle kann von jeder Klasse implementiert werden. Wenn dieser Wert von einer der implementierenden Klassen geändert wurde, wird dies für andere implementierende Klassen irreführend sein. Die Schnittstelle ist im Grunde eine Referenz zum Kombinieren von zwei korrelierten, aber unterschiedlichen Entitäten. Aus diesem Grund ist die deklarierende Variable innerhalb der Schnittstelle implizit endgültig und auch statisch, da die Schnittstelle nicht instanziiert werden kann.


0

Stellen Sie sich eine Webanwendung vor, für die Sie eine Schnittstelle definiert haben und die von anderen Klassen implementiert wird. Da Sie keine Instanz der Schnittstelle erstellen können, um auf die Variablen zuzugreifen, benötigen Sie ein statisches Schlüsselwort. Da es statisch ist, wirkt sich jede Änderung des Werts auf andere Instanzen aus, die ihn implementiert haben. Um dies zu verhindern, definieren wir sie als endgültig.


0

Gerade in Eclipse ausprobiert, ist die Variable in der Schnittstelle standardmäßig endgültig, sodass Sie sie nicht ändern können. Im Vergleich zur übergeordneten Klasse sind die Variablen definitiv veränderbar. Warum? Aus meiner Sicht ist die Variable in der Klasse ein Attribut, das von Kindern geerbt wird, und Kinder können es entsprechend ihrem tatsächlichen Bedarf ändern. Im Gegenteil, die Schnittstelle definiert nur das Verhalten, nicht das Attribut. Der einzige Grund, Variablen in die Schnittstelle einzufügen, besteht darin, sie als Konstanten zu verwenden, die sich auf diese Schnittstelle beziehen. Dies ist jedoch keine gute Praxis gemäß folgendem Auszug:

"Das Platzieren von Konstanten in einer Schnittstelle war in den frühen Tagen von Java eine beliebte Technik, aber heute betrachten viele die Verwendung von Schnittstellen als unangenehm, da Schnittstellen sich mit den von einem Objekt bereitgestellten Diensten befassen sollten, nicht mit seinen Daten. Auch die verwendeten Konstanten von einer Klasse sind normalerweise ein Implementierungsdetail, aber das Platzieren in einer Schnittstelle befördert sie zur öffentlichen API der Klasse. "

Ich habe auch versucht, entweder statisch zu setzen oder überhaupt keinen Unterschied zu machen. Der Code lautet wie folgt:

public interface Addable {
    static int count = 6;

    public int add(int i);

}

public class Impl implements Addable {

    @Override
    public int add(int i) {
        return i+count;
    }
}

public class Test {

    public static void main(String... args) {
        Impl impl = new Impl();

        System.out.println(impl.add(4));
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.