method - java jframe tutorial




Warum kann ich keine statische Methode in einer Java-Schnittstelle definieren? (16)

Warum kann ich keine statische Methode in einer Java-Schnittstelle definieren?

Eigentlich kannst du in Java 8.

Gemäß Java- docs.oracle/staticMethod :

Eine statische Methode ist eine Methode, die der Klasse zugeordnet ist, in der sie definiert ist, und nicht mit einem Objekt. Jede Instanz der Klasse teilt ihre statischen Methoden

In Java 8 kann eine Schnittstelle Standardmethoden und statische Methoden haben . Dies erleichtert uns die Organisation von Hilfsmethoden in unseren Bibliotheken. Wir können statische Methoden für eine Schnittstelle in derselben Schnittstelle und nicht in einer separaten Klasse beibehalten.

Beispiel für eine Standardmethode:

list.sort(ordering);

Anstatt von

Collections.sort(list, ordering);

Beispiel für eine statische Methode (aus dem docs.oracle/staticMethod selbst):

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

Hier ist das Beispiel:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

Natürlich wird das nicht funktionieren. Aber warum nicht?

Eines der möglichen Probleme wäre, was passiert, wenn Sie anrufen:

IXMLizable.newInstanceFromXML(e);

In diesem Fall, denke ich, sollte es einfach eine leere Methode aufrufen (zB {}). Alle Unterklassen wären gezwungen, die statische Methode zu implementieren, so dass sie alle beim Aufruf der statischen Methode in Ordnung wären. Warum ist das nicht möglich?

EDIT: Ich denke, ich suche nach einer Antwort, die tiefer ist als "weil Java so ist".

Gibt es einen besonderen technologischen Grund, warum statische Methoden nicht überschrieben werden können? Das heißt, warum haben die Designer von Java beschlossen, Instanzmethoden außer Kraft zu setzen, aber nicht statische Methoden?

EDIT: Das Problem mit meinem Design ist, ich versuche, Schnittstellen zu verwenden, um eine Kodierungskonvention durchzusetzen.

Das heißt, das Ziel der Schnittstelle ist zweifach:

  1. Ich möchte, dass die IXMLizable-Schnittstelle mir erlaubt, Klassen zu konvertieren, die es in XML-Elemente implementieren (mit Polymorphismus, funktioniert gut).

  2. Wenn jemand eine neue Instanz einer Klasse erstellen möchte, die die IXMLizable-Schnittstelle implementiert, werden sie immer wissen, dass es einen statischen Konstruktor newInstanceFromXML (Element e) geben wird.

Gibt es einen anderen Weg, dies zu gewährleisten, als nur einen Kommentar in die Oberfläche zu schreiben?

EDIT: Ab Java 8 sind nun statische Methoden in Schnittstellen erlaubt.


Java 8 erlaubt statische Schnittstellenmethoden

Mit Java 8 können Schnittstellen statische Methoden haben. Sie können auch konkrete Instanzmethoden, aber keine Instanzfelder haben.

Hier sind wirklich zwei Fragen:

  1. Warum konnten in den schlechten alten Zeiten keine Interfaces statische Methoden enthalten?
  2. Warum können statische Methoden nicht überschrieben werden?

Statische Methoden in Schnittstellen

Es gab keinen starken technischen Grund, warum Interfaces in früheren Versionen keine statischen Methoden haben konnten. Dies wird durch das Poster einer doppelten Frage gut zusammengefasst. Statische Interfacemethoden wurden ursprünglich als kleine Sprachveränderung betrachtet, und dann gab es einen offiziellen Vorschlag , sie in Java 7 hinzuzufügen, aber sie wurde später wegen unvorhergesehener Komplikationen fallengelassen.

Abschließend wurden in Java 8 statische Schnittstellenmethoden sowie überschreibbare Instanzmethoden mit einer Standardimplementierung eingeführt. Sie können jedoch immer noch keine Instanzfelder haben. Diese Funktionen sind Teil der Unterstützung für Lambda-Ausdrücke, und Sie können mehr darüber in Teil H von JSR 335 lesen .

Überschreiben von statischen Methoden

Die Antwort auf die zweite Frage ist etwas komplizierter.

Statische Methoden sind zur Kompilierzeit auflösbar. Die dynamische Verteilung ist für Instanzmethoden sinnvoll, bei denen der Compiler den konkreten Typ des Objekts nicht ermitteln kann und daher die aufzurufende Methode nicht auflösen kann. Das Aufrufen einer statischen Methode erfordert jedoch eine Klasse, und da diese Klasse statisch - zur Kompilierzeit - bekannt ist, ist dynamischer Versand nicht erforderlich.

Ein kleiner Hintergrund darüber, wie Instanzmethoden funktionieren, ist notwendig, um zu verstehen, was hier vor sich geht. Ich bin mir sicher, dass die tatsächliche Implementierung ganz anders ist, aber lassen Sie mich meine Vorstellung von Methodenversand erklären, der genau beobachtete Verhaltensweisen modelliert.

Geben Sie vor, dass jede Klasse über eine Hash-Tabelle verfügt, die Methodensignaturen (Name und Parametertypen) einem tatsächlichen Codeabschnitt zuordnet, um die Methode zu implementieren. Wenn die virtuelle Maschine versucht, eine Methode für eine Instanz aufzurufen, fragt sie das Objekt nach seiner Klasse ab und sucht die angeforderte Signatur in der Tabelle der Klasse. Wenn ein Methodenkörper gefunden wird, wird er aufgerufen. Andernfalls wird die Elternklasse der Klasse erhalten, und die Suche wird dort wiederholt. Dies wird fortgesetzt, bis die Methode gefunden wurde oder keine übergeordneten Klassen mehr vorhanden sind. Dies führt zu einem NoSuchMethodError .

Wenn eine Oberklasse und eine Unterklasse beide einen Eintrag in ihren Tabellen für dieselbe Methodensignatur haben, wird zuerst die Version der Unterklasse angetroffen und die Version der Oberklasse wird nie verwendet - dies ist eine "Überschreibung".

Angenommen, wir überspringen die Objektinstanz und beginnen einfach mit einer Unterklasse. Die Auflösung könnte wie oben beschrieben ablaufen und Ihnen eine Art "überschreibbare" statische Methode geben. Die Auflösung kann jedoch zur Kompilierungszeit erfolgen, da der Compiler von einer bekannten Klasse aus startet und nicht bis zur Laufzeit wartet, um ein Objekt eines nicht spezifizierten Typs für seine Klasse abzufragen. Es hat keinen Sinn, eine statische Methode zu "überschreiben", da man immer die Klasse angeben kann, die die gewünschte Version enthält.

Konstruktor "Schnittstellen"

Hier ist ein wenig mehr Material, um die letzte Bearbeitung der Frage zu behandeln.

Es klingt, als ob Sie eine konstruktorähnliche Methode für jede Implementierung von IXMLizable effektiv IXMLizable . Vergessen Sie zu versuchen, dies für eine Minute mit einer Schnittstelle zu erzwingen, und geben Sie vor, dass Sie einige Klassen haben, die diese Anforderung erfüllen. Wie würdest du es benutzen?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

Da Sie den konkreten Typ Foo explizit benennen müssen, wenn Sie das neue Objekt "konstruieren", kann der Compiler überprüfen, dass es tatsächlich die notwendige Factory-Methode hat. Und wenn nicht, na und? Wenn ich ein IXMLizable implementieren IXMLizable , dem der "Konstruktor" fehlt, und ich eine Instanz erstelle und sie an Ihren Code weitergebe, ist es ein IXMLizable mit allen notwendigen Schnittstellen.

Die Konstruktion ist Teil der Implementierung, nicht die Schnittstelle. Jeder Code, der erfolgreich mit der Schnittstelle funktioniert, interessiert sich nicht für den Konstruktor. Jeder Code, der sich um den Konstruktor kümmert, muss trotzdem den konkreten Typ kennen, und die Schnittstelle kann ignoriert werden.


Angenommen, in Schnittstellen sind statische Methoden erlaubt: * Sie würden alle implementierenden Klassen dazu zwingen, diese Methode zu deklarieren. * Schnittstellen würden normalerweise durch Objekte verwendet werden, so dass die einzigen effektiven Methoden auf diesen die nicht-statischen wären. * Jede Klasse, die eine bestimmte Schnittstelle kennt, könnte ihre statischen Methoden aufrufen. Daher würde die statische Methode einer Implementierungsklasse darunter genannt werden, aber die Aufruferklasse weiß nicht welche. Wie kann ich es wissen? Es hat keine Instantiierung, um das zu erraten!

Es wird angenommen, dass Schnittstellen verwendet werden, wenn mit Objekten gearbeitet wird. Auf diese Weise wird ein Objekt aus einer bestimmten Klasse instanziiert, so dass diese letzte Sache gelöst ist. Die aufrufende Klasse muss nicht wissen, welche bestimmte Klasse existiert, weil die Instanziierung von einer dritten Klasse durchgeführt werden kann. Die aufrufende Klasse kennt also nur die Schnittstelle.

Wenn wir möchten, dass dies auf statische Methoden erweitert wird, sollten wir die Möglichkeit haben, vorher eine implementierende Klasse anzugeben und dann einen Verweis auf die aufrufende Klasse zu übergeben. Dies könnte die Klasse über die statischen Methoden in der Schnittstelle verwenden. Aber was ist der Unterschied zwischen dieser Referenz und einem Objekt? Wir brauchen nur ein Objekt, das repräsentiert, was es war. Jetzt repräsentiert das Objekt die alte Klasse und könnte eine neue Schnittstelle einschließlich der alten statischen Methoden implementieren - diese sind jetzt nicht-statisch.

Metaklassen dienen diesem Zweck. Sie können versuchen, die Klasse Java Klasse. Aber das Problem ist, dass Java dafür nicht flexibel genug ist. Sie können keine Methode im Klassenobjekt einer Schnittstelle deklarieren.

Dies ist ein Meta-Problem - wenn Sie ass tun müssen

..blah blah

Wie auch immer, Sie haben eine einfache Problemumgehung - indem Sie die Methode mit derselben Logik nicht statisch machen. Aber dann müssten Sie zuerst ein Objekt erstellen, um die Methode aufzurufen.


Da statische Methoden in Unterklassen nicht überschrieben werden können, können sie nicht abstrakt sein. Und alle Methoden in einer Schnittstelle sind de facto abstrakt.


Eine Schnittstelle kann niemals statisch dereferenziert werden, zB ISomething.member . Eine Schnittstelle wird immer über eine Variable dereferenziert, die auf eine Instanz einer Unterklasse der Schnittstelle verweist. Somit kann eine Schnittstellenreferenz niemals wissen, auf welche Unterklasse sie sich ohne eine Instanz ihrer Unterklasse bezieht.

Die nächste Annäherung an eine statische Methode in einer Schnittstelle wäre also eine nicht-statische Methode, die "dies" ignoriert, dh nicht auf nicht statische Mitglieder der Instanz zugreift. Bei der Abstraktion auf niedriger Ebene ist jede nicht statische Methode (nach dem Nachschlagen in einer beliebigen vtable) wirklich nur eine Funktion mit einem Klassenbereich, der "dieses" als impliziten formalen Parameter akzeptiert. Siehe Scalas Singleton-Objekt und Interoperabilität mit Java als Beweis für dieses Konzept. Und so ist jede statische Methode eine Funktion mit Klassenumfang, die keinen "this" -Parameter benötigt. So kann normalerweise eine statische Methode statisch aufgerufen werden, aber wie bereits erwähnt, hat eine Schnittstelle keine Implementierung (ist abstrakt).

Um also einer statischen Methode in einer Schnittstelle am nächsten zu kommen, verwenden Sie eine nicht statische Methode und greifen dann nicht auf die nicht statischen Instanzmitglieder zu. Es gibt keinen möglichen Leistungsvorteil auf andere Weise, da es keine Möglichkeit gibt, ein ISomething.member() statisch zu kompilieren. Der einzige Vorteil, den ich an einer statischen Methode in einer Schnittstelle sehe, ist, dass sie ein implizites "Dies" nicht eingibt (dh ignoriert) und somit den Zugriff auf alle nicht-statischen Instanzenmitglieder verbietet. Dies würde implizit erklären, dass die Funktion, die nicht auf "dieses" zugreift, unmündig und nicht nur schreibend in Bezug auf ihre umschließende Klasse ist. Aber eine Deklaration von "statisch" in einem Interface ISomething würde auch Leute verwirren, die versuchten, mit ISomething.member() was einen Compilerfehler verursachen würde. Ich nehme an, wenn der Compilerfehler ausreichend erklärend wäre, wäre es besser als zu versuchen, Leute darüber aufzuklären, eine nicht-statische Methode zu benutzen, um das zu erreichen, was sie wollen (anscheinend meistens Fabrikmethoden), wie wir es hier tun (und für 3 wiederholt wurde) Fragen und Antworten auf dieser Website), so ist es offensichtlich ein Problem, das für viele Menschen nicht intuitiv ist. Ich musste eine Weile darüber nachdenken, um das richtige Verständnis zu bekommen.

Um ein veränderbares statisches Feld in einer Schnittstelle zu erhalten, verwenden Sie nicht statische Getter- und Setter-Methoden in einer Schnittstelle, um auf das statische Feld in der Unterklasse zuzugreifen. Side Note, scheinbar unveränderbare Statiken können in einer Java-Schnittstelle mit static final deklariert werden.


Erstens sind alle Sprachentscheidungen Entscheidungen der Sprachersteller. Es gibt nichts in der Welt des Software-Engineerings oder sprachdefinierenden oder Compiler / Interpreter-Schreibens, das besagt, dass eine statische Methode nicht Teil einer Schnittstelle sein kann. Ich habe ein paar Sprachen erstellt und Compiler für sie geschrieben - es geht nur darum, sinnvolle Semantiken zu definieren. Ich würde argumentieren, dass die Semantik einer statischen Methode in einer Schnittstelle bemerkenswert klar ist - selbst wenn der Compiler die Auflösung der Methode auf Laufzeit verschieben muss.

Zweitens, dass wir statische Methoden überhaupt verwenden, gibt es einen triftigen Grund dafür, ein Schnittstellenmuster zu haben, das statische Methoden beinhaltet - ich kann für keinen von euch sprechen, aber ich verwende regelmäßig statische Methoden.

Die wahrscheinlich richtige Antwort ist, dass zum Zeitpunkt der Definition der Sprache kein Bedarf an statischen Methoden in Schnittstellen bestand. Java ist im Laufe der Jahre sehr gewachsen und dies ist ein Gegenstand, der offensichtlich Interesse geweckt hat. Dass es für Java 7 angeschaut wurde, deutet darauf hin, dass es auf ein Niveau von Interesse gestiegen ist, das zu einem Sprachwechsel führen könnte. Ich für meinen Teil bin glücklich, wenn ich ein Objekt nicht mehr instanziieren muss, damit ich meine nicht statische Getter-Methode aufrufen kann, um auf eine statische Variable in einer Unterklasseninstanz zuzugreifen ...


Ich denke, Java hat keine statischen Interface-Methoden, weil Sie sie nicht brauchen. Du denkst vielleicht, dass du es tust, aber ... Wie würdest du sie benutzen? Wenn Sie sie gerne mögen

MyImplClass.myMethod()

dann müssen Sie es nicht in der Schnittstelle deklarieren. Wenn Sie sie gerne mögen

myInstance.myMethod()

dann sollte es nicht statisch sein. If you are actually going to use first way, but just want to enforce each implementation to have such static method, then it is really a coding convention, not a contract between instance that implements an interface and calling code.

Interfaces allow you to define contract between instance of class that implement the interface and calling code. And java helps you to be sure that this contract is not violated, so you can rely on it and don't worry what class implements this contract, just "someone who signed a contract" is enough. In case of static interfaces your code

MyImplClass.myMethod()

does not rely on the fact that each interface implementation has this method, so you do not need java to help you to be sure with it.


Interfaces beschäftigen sich mit Polymorphie, die inhärent mit Objektinstanzen, nicht mit Klassen verknüpft ist. Daher ist im Kontext einer Schnittstelle statisch nicht sinnvoll.


Mehrere Antworten haben die Probleme mit dem Konzept der überschreibbaren statischen Methoden diskutiert. Manchmal stößt man jedoch auf ein Muster, bei dem es so aussieht, als ob man es nur benutzen möchte.

Ich arbeite zum Beispiel mit einem objektrelationalen Layer, der Wertobjekte hat, aber auch Befehle zum Manipulieren der Wertobjekte. Aus verschiedenen Gründen muss jede Wertobjektklasse einige statische Methoden definieren, die es dem Framework ermöglichen, die Befehlsinstanz zu finden. Um beispielsweise eine Person zu erstellen, würden Sie Folgendes tun:

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

und um eine Person nach ID zu laden

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

Dies ist ziemlich bequem, hat jedoch seine Probleme; Insbesondere die Existenz der statischen Methoden kann in der Schnittstelle nicht erzwungen werden. Eine überschreibbare statische Methode in der Schnittstelle wäre genau das, was wir brauchen würden, wenn es nur irgendwie funktionieren könnte.

EJBs lösen dieses Problem, indem sie eine Home-Schnittstelle haben; Jedes Objekt weiß, wie es sein Zuhause findet und das Heim enthält die "statischen" Methoden. Auf diese Weise können die "statischen" Methoden bei Bedarf überschrieben werden, und Sie können die normale Schnittstelle ("Remote") nicht mit Methoden überladen, die nicht für eine Instanz Ihrer Bean gelten. Machen Sie einfach die normale Schnittstelle eine "getHome ()" -Methode angeben. Gibt eine Instanz des Home-Objekts zurück (das könnte ein Singleton sein, nehme ich an), und der Aufrufer kann Operationen ausführen, die alle Person-Objekte betreffen.


Mit dem Aufkommen von Java 8 ist es jetzt möglich, standardmäßige und statische Methoden in der Schnittstelle zu schreiben. docs.oracle/staticMethod

Beispielsweise:

public interface Arithmetic {

    public int add(int a, int b);

    public static int multiply(int a, int b) {
        return a * b;
    }
}
public class ArithmaticImplementation implements Arithmetic {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = Arithmetic.multiply(2, 3);
        System.out.println(result);
    }
}

Ergebnis : 6

TIPP: Der Aufruf einer statischen Schnittstellenmethode muss nicht von einer Klasse implementiert werden. Dies geschieht jedoch, weil für statische Methoden in Interfaces dieselben Regeln für statische Methoden in Superklassen gelten.


Nun, ohne Generika sind statische Interfaces nutzlos, da alle statischen Methodenaufrufe zur Kompilierungszeit aufgelöst werden. Also, es gibt keinen wirklichen Nutzen für sie.

Bei Generika haben sie Verwendung - mit oder ohne eine Standardimplementierung. Offensichtlich müsste es Vorrang haben und so weiter. Meine Vermutung ist jedoch, dass eine solche Verwendung nicht sehr OO war (wie die anderen Antworten stumpfsinnig aufzeigen) und daher nicht als die Mühe wert betrachtet wurde, die sie zur sinnvollen Implementierung benötigen würden.


Schnittstellen stellen nur eine Liste von Dingen zur Verfügung, die eine Klasse zur Verfügung stellt, nicht eine tatsächliche Implementierung dieser Dinge, was Ihr statisches Element ist.

Wenn Sie Statiken verwenden möchten, verwenden Sie eine abstrakte Klasse und erben Sie sie, andernfalls entfernen Sie die statische.

Ich hoffe, das hilft!


Statische Methoden sind nicht virtuell wie Instanzmethoden, also vermute ich, dass die Java-Designer entschieden haben, dass sie diese nicht in Interfaces wollen.

Sie können jedoch Klassen, die statische Methoden enthalten, in Schnittstellen einfügen. Du könntest das versuchen!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}

Um dies zu lösen: error: fehlender Methodenkörper oder deklarieren Sie abstract static void main (String [] args);

interface I
{
    int x=20;
    void getValue();
    static void main(String[] args){};//Put curly braces 
}
class InterDemo implements I
{
    public void getValue()
    {
    System.out.println(x);
    }
    public static void main(String[] args)
    {
    InterDemo i=new InterDemo();
    i.getValue();   
    }

}

Ausgabe: 20

Jetzt können wir die statische Methode in der Schnittstelle verwenden


Was ist die Notwendigkeit der statischen Methode in der Schnittstelle, statische Methoden werden grundsätzlich verwendet, wenn Sie keine Instanz von Objekt erstellen müssen, ist die Idee der Schnittstelle zu bringen OOP-Konzepte mit der Einführung der statischen Methode bringen Sie vom Konzept abweichen.


Why can't I define a static method in a Java interface?

Alle Methoden in einer Schnittstelle sind explizit abstrakt und können daher nicht als statisch definiert werden, da statische Methoden nicht abstrakt sein können.





static-methods