Warum sind Schnittstellenvariablen in Java standardmäßig statisch und endgültig?
Warum sind Schnittstellenvariablen in Java standardmäßig statisch und endgültig?
Antworten:
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.
static
Modifikator ist völlig falsch. Die öffentlichen Instanzvariablen einer Klasse sind Teil ihrer Schnittstelle, und es gibt keinen Grund, warum sie nicht interface
wie Instanzmethoden in Java abstrahiert werden sollten. Es spielt keine Rolle, dass ein Java interface
nicht direkt instanziiert werden kann - Sie können immer noch Instanzen von Klassen haben, die das implementieren, interface
und es ist sinnvoll zu verlangen, dass sie eine bestimmte öffentliche Instanzvariable haben. Der Teil über final
bietet überhaupt keine Erklärung - er beschreibt nur, was final
bedeutet.
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 !!!
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.
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.
( Dies ist keine philosophische, sondern eher eine praktische Antwort ). Das Erfordernis eines static
Modifikators 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 interface
Felder 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 interface
Eigenschaft nicht explizit final
von 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, Actionable
den 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 NuclearAction
von einer anderen Klasse beeinflusst werden CleanAction
, wenn sie performAction()
aufgerufen wird, nachdem sie CleanAction
ausgefü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 interface
diese Variablen verwenden wird, müssen sie implizit sein final
.
Weil alles andere Teil der Implementierung ist und Schnittstellen keine Implementierung enthalten können.
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.
static final
vor der Variablen geschrieben sehen, die tatsächlich statisch und endgültig ist.
statisch - weil die Schnittstelle keine Instanz haben kann. und schließlich - weil wir es nicht ändern müssen.
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
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
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 .
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.
In der Java
Schnittstelle 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 final
die sich von einer Instanzvariablen unterscheidet.
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.
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.
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));
}
}