Warum keine statischen Methoden in Interfaces, aber statische Felder und innere Klassen OK? [Pre-Java 8] [Duplikat]

StackOverflow https://stackoverflow.com/questions/129267

  •  02-07-2019
  •  | 
  •  

Frage

    

Diese Frage bereits eine Antwort hier:

         

Es gab ein paar Fragen hier gefragt, warum Sie statische Methoden in Schnittstellen nicht definieren können, aber keiner von ihnen eine grundlegende Inkonsistenz adressieren: Warum können Sie festlegen, statische Felder und statische innere Typen innerhalb einer Schnittstelle, aber nicht statische Methoden ?

Statische innere Typen sind vielleicht kein fairer Vergleich, denn das ist nur syntaktischer Zucker, die eine neue Klasse erzeugt, aber warum Felder, aber diese Methoden nicht?

Ein Argument gegen statische Methoden innerhalb Schnittstellen ist, dass sie die virtuelle Tabelle Lösungsstrategie von der JVM verwendet bricht, aber sollte das nicht gelten gleichermaßen für statische Felder, das heißt der Compiler kann es nur inline?

Konsequenz ist, was ich will, und Java sollte keine Statik jeglicher Form innerhalb einer Schnittstelle entweder unterstützt oder es sollte sich konsistent und läßt sein.

War es hilfreich?

Lösung

Ein offiziellen Vorschlag statische Methoden in Interfaces zu ermöglichen gemacht wurde in Java 7. Dieser Vorschlag unter Projekt Münze gemacht wird.

Meine persönliche Meinung ist, dass es eine gute Idee ist. Es gibt keine technischen Schwierigkeiten bei der Umsetzung, und es ist eine sehr logische, vernünftige Sache zu tun. Es gibt mehrere Vorschläge im Projekt-Münze, die ich hoffe, dass nie Teil der Java-Sprache worden, aber das ist eine, die eine Menge von APIs bereinigen könnte. Zum Beispiel kann der Collections Klasse statische Methoden List jede Implementierung Manipulieren; diejenigen, könnten in der List Schnittstelle aufgenommen werden.


Update: In der Java Posse Podcast # 234, Joe D'Arcy kurz erwähnt den Vorschlag und sagte, dass es „Komplex“ und würde wahrscheinlich nicht unter Projekt Münze machen in.


Update: Während sie es nicht in Projekt-Münze für Java gemacht hat 7, Java 8 tut Unterstützung statische Funktionen in Schnittstellen.

Andere Tipps

Ich werde mit meinem Haustiere Theorie mit diesem gehen, das ist, dass der Mangel an Konsistenz in diesem Fall eine Frage der Bequemlichkeit ist eher als Design oder Notwendigkeit, da ich kein überzeugendes Argument gehört habe, dass es entweder von diesen beiden.

Statische Felder gibt es (a), weil sie dort 1,0 in JDK waren, und viele zweifelhaften Entscheidungen wurden in JDK 1.0, und (b) static final Felder in Schnittstellen sind das nächste Sache, java mußten Konstanten zu der Zeit gemacht.

Statische innere Klassen in Schnittstellen erlaubt wurden, weil das ist rein syntaktischer Zucker -. Die innere Klasse ist alles nicht wirklich mit der übergeordneten Klasse zu tun

So statische Methoden sind nicht nur erlaubt, weil es kein zwingender Grund, dies zu tun; Konsistenz ist nicht so überzeugend, den Status quo zu ändern.

Natürlich könnte dies ohne etwas zu zerbrechen in Zukunft JLS Versionen zugelassen werden.

Es gibt nie einen Punkt, um eine statische Methode in einer Schnittstelle zu deklarieren. Sie können nicht durch den normalen Anruf MyInterface.staticMethod ausgeführt werden (). (EDIT: Da der letzte Satz einige Leute verwirrt, ruft MyClass.staticMethod () führt genau die Umsetzung von Static auf MyClass, die, wenn MyClass eine Schnittstelle ist nicht vorhanden) Wenn Sie sie aufrufen, indem Sie die implementierende Klasse MyImplementor.staticMethod Angabe () dann müssen Sie die tatsächliche Klasse kennen, so ist es unerheblich, ob die Schnittstelle enthält oder nicht.

Noch wichtiger ist, statische Methoden nie außer Kraft gesetzt werden, und wenn Sie versuchen zu tun:

MyInterface var = new MyImplementingClass();
var.staticMethod();

die Regeln für die statische sagen, dass das Verfahren in dem deklarierten Typ von var definiert ausgeführt werden muss. Da es sich um eine Schnittstelle handelt, ist dies nicht möglich.

Sie können natürlich immer das Schlüsselwort static aus dem Verfahren entfernen. Alles wird gut funktionieren. Sie können einige Warnungen zu unterdrücken, wenn es von einer Instanz-Methode aufgerufen wird.

, um einige der Kommentare unten zu beantworten, der Grund, warum Sie kann nicht ausgeführt werden „result = MyInterface.staticMethod ()“ ist, dass es müssen die Version des Verfahrens in MyInterface definiert ausführen würde. Aber es kann nicht eine Version in MyInterface definiert sein, weil es sich um eine Schnittstelle ist. Es muss nicht Code per Definition.

Der Zweck der Schnittstellen ist es, einen Vertrag zu definieren, ohne eine Implementierung bereitstellt. Daher können Sie nicht statische Methoden haben, weil sie eine Implementierung haben bereits in der Schnittstelle haben würde, da Sie nicht statische Methoden außer Kraft setzen können. In Bezug auf Felder werden nur statischer final fields erlaubt, das ist im wesentlichen Konstanten (in 1.5+ Sie auch Aufzählungen in Schnittstellen haben können). Die Konstanten sind dort zu helfen, die Schnittstelle ohne magische Zahlen zu definieren.

BTW, gibt es keine Notwendigkeit, explizit static final Modifikatoren für Felder in Schnittstellen, da nur statische endgültige Felder erlaubt sind.

angeben

Dies ist ein alter Thread, aber das ist etwas sehr wichtige Frage für alle. Da ich dies heute nur bemerkt, so versuche ich es in sauberen Weise zu erklären:

Der Hauptzweck der Schnittstelle ist, etwas zu schaffen, das unimplementable ist, so dass, wenn sie zur Verfügung stellen

  

statische Methoden erlaubt werden

Dann können Sie diese Methode aufrufen mit interfaceName.staticMethodName () , aber das ist nicht implementierte Methode und enthält nichts. So ist es nutzlos, statische Methoden zu ermöglichen. Deshalb ist diese liefern sie nicht.

  

statische Felder sind erlaubt

da Felder nicht implementierbar sind, durch implementierbar ich meine Sie keine logische Operation im Feld durchführen können, können Sie den Betrieb auf dem Feld tun. Sie sind also nicht das Verhalten von Feld ändern, die ist, warum sie erlaubt sind.

  

Innere Klassen sind erlaubt

Innere Klassen werden, da nach der Kompilierung verschiedene Klassendatei der Inneren Klasse darf sagen erstellt $ Interface InnerClassName.class , so dass im Grunde Sie Implementierung in verschiedenen Unternehmen bieten alle zusammen, aber nicht in der Schnittstelle. So Implementierung in der Inneren Klassen vorgesehen ist.

Ich hoffe, dies würde helfen.

Eigentlich manchmal gibt es Gründe, jemand aus statischen Methoden profitieren kann. Sie können als Factory-Methoden für die Klassen verwendet werden, die die Schnittstelle implementieren. Zum Beispiel ist das der Grund, warum wir Collection-Schnittstelle und die Kollektionen Klasse in openjdk jetzt haben. So gibt es Workarounds wie immer - eine andere Klasse mit einem privaten Konstruktor bereitzustellen, die als „Namensraum“ für die statischen Methoden dienen

.

Vor der Java 5, eine gemeinsame Nutzung für statische Felder war:

interface HtmlConstants {
    static String OPEN = "<";
    static String SLASH_OPEN = "</";
    static String CLOSE = ">";
    static String SLASH_CLOSE = " />";
    static String HTML = "html";
    static String BODY = "body";
    ...
}

public class HtmlBuilder implements HtmlConstants { // implements ?!?
    public String buildHtml() {
       StringBuffer sb = new StringBuffer();
       sb.append(OPEN).append(HTML).append(CLOSE);
       sb.append(OPEN).append(BODY).append(CLOSE);
       ...
       sb.append(SLASH_OPEN).append(BODY).append(CLOSE);
       sb.append(SLASH_OPEN).append(HTML).append(CLOSE);
       return sb.toString();
    }
}

Das bedeutete HtmlBuilder würde sich nicht konstant zu qualifizieren, so könnte es benutzen OPEN statt HtmlConstants.OPEN

Geräte auf diese Weise zu verwenden ist letztlich verwirrend.

Jetzt mit Java 5, haben wir die import static Syntax, um den gleichen Effekt zu erzielen:

private final class HtmlConstants {
    ...
    private HtmlConstants() { /* empty */ }
}

import static HtmlConstants.*;
public class HtmlBuilder { // no longer uses implements
    ...
}

Es gibt keinen wirklichen Grund für die nicht statische Methoden in Schnittstellen außer mit: der Programmiersprache Java Designer will es nicht so. Aus technischer Sicht wäre es sinnvoll, sie zu ermöglichen. Schließlich einer abstrakten Klasse können sie auch haben. Ich gehe davon aus, aber habe es nicht testen, dass Sie „Handarbeit“ Byte-Code, wo die Schnittstelle über eine statische Methode hat und es sollte imho ohne Probleme arbeiten, um die Methode aufzurufen und / oder die Schnittstelle, wie sie üblicherweise verwendet werden.

Ich frage mich oft, warum statische Methoden überhaupt? Sie haben ihren Nutzen, aber Paket / Namensraum Ebene Methoden würden wahrscheinlich decken 80 von dem, was statischen Methoden zum Einsatz.

Zwei Hauptgründe in dem Sinne:

  1. Statische Methoden in Java kann nicht von den Unterklassen außer Kraft gesetzt werden, und dies ist ein viel größeres Angebot für Methoden als statische Felder. In der Praxis habe wollte ich nie auch nur ein Feld in einer Unterklasse außer Kraft zu setzen, aber ich Methoden des ganze Zeit außer Kraft setzen. So statische Methoden, die verhindert, dass eine Klasse der Umsetzung die Schnittstelle aus der eigenen Anwendung dieser Methode liefert, die weitgehend den Zweck eine Schnittstelle zu verwenden.

  2. Schnittstellen sollen nicht den Code haben; Das ist, was abstrakte Klassen sind für. Der springende Punkt einer Schnittstelle ist Sie möglicherweise unabhängige Objekte sprechen zu lassen, die alle passieren eine bestimmte Reihe von Methoden. Eigentlich Bereitstellung ist eine Implementierung dieser Methoden außerhalb der Grenzen dessen, was Schnittstellen vorgesehen sind, sein.

Statische Methoden werden an eine Klasse gebunden. In Java ist eine Schnittstelle technisch nicht eine Klasse, es ist eine Art, aber keine Klasse (also das Schlüsselwort implementiert und Schnittstellen erweitern nicht Object). Da Schnittstellen nicht Klassen sind, können sie nicht statische Methoden haben, da es keine tatsächliche Klasse zu befestigen.

Sie können InterfaceName.class nennen das Klassenobjekt zu erhalten entsprechend der Schnittstelle, aber die Klasse Klasse heißt es ausdrücklich, dass es Klassen und Schnittstellen in einer Java-Anwendung darstellt. Allerdings ist die Schnittstelle selbst nicht als eine Klasse behandelt, und daher kann man nicht eine statische Methode befestigen.

Nur static final Felder können in einer Schnittstelle deklariert werden (ähnlich wie Methoden, die auch öffentlich sind, wenn Sie das „public“ Schlüsselwort nicht enthalten, statische Felder sind „final“ mit oder ohne das Schlüsselwort).

Dies sind nur Werte und werden buchstäblich kopiert werden, wo sie bei der Kompilierung verwendet werden, so dass Sie nie wirklich „Anruf“ statische Felder zur Laufzeit. eine statische Methode zu haben wäre die gleiche Semantik nicht haben, da es ohne eine Implementierung einer Schnittstelle Aufruf beinhalten würde, die Java nicht erlaubt.

Der Grund dafür ist, dass alle in einer Schnittstelle definierten Methoden abstrakt sind, ob Sie explizit, dass Modifikator erklären. Eine abstrakte statische Methode ist keine zulässige Kombination von Modifikatoren, da statischen Methoden nicht in der Lage sind außer Kraft gesetzt werden.

Wie, warum Schnittstellen erlauben statische Felder. Ich habe das Gefühl, dass ein „Feature“ in Betracht gezogen werden sollte. Die einzige Möglichkeit, die ich denken kann zu einer Gruppe Konstanten sein würde, die Implementierungen der Schnittstelle interessiert sein würde.

Ich bin damit einverstanden, dass die Konsistenz ein besserer Ansatz gewesen wäre. Keine statischen Mitglieder sollten in einer Schnittstelle erlaubt werden.

Ich glaube, dass statische Methoden können, ohne ein Objekt und die Schnittstelle nicht erlaubt, zugegriffen werden, um ein Objekt zu erstellen, wie die Programmierer von der Verwendung der Interface-Methoden direkt und nicht von der implementierten Klasse zu beschränken. Aber wenn Sie eine statische Methode in einer Schnittstelle zu definieren, können Sie es direkt zugreifen, ohne deren Umsetzung. So statische Methoden sind in Schnittstellen nicht zulässig. Ich glaube nicht, dass die Konsistenz ein Anliegen sein sollte.

Java 1.8-Schnittstelle statische Methode Methoden sichtbar ist nur eine Schnittstelle, wenn wir den methodSta1 () -Methode von der InterfaceExample Klasse zu entfernen, wir werden es nicht für das InterfaceExample Objekt nutzen können. Doch wie andere statische Methoden können wir Schnittstelle statische Methoden mit dem Klassennamen verwenden. Zum Beispiel wird eine gültige Aussage sein: exp1.methodSta1 ();

So nach unten Beispiel suchen, können wir sagen: 1) Java-Schnittstelle statische Methode ist Teil der Schnittstelle, können wir es nicht für die Umsetzung Klassenobjekte verwenden können.

2) Java-Schnittstelle statische Methoden sind gut für Dienstmethoden bereitstellt, beispielsweise null zu überprüfen, Sammlung Sortierung, log etc.

3) Java-Schnittstelle statische Methode hilft uns, die Sicherheit bei der Bereitstellung, indem sie keine Implementierungsklassen (InterfaceExample), um sie außer Kraft zu setzen.

4) Wir können nicht Schnittstelle statische Methode für Objektklasse Methoden definieren, werden wir Compiler-Fehler wie „Diese statische Methode kann nicht darüber hinwegtäuschen, die Instanz-Methode von Object“ erhalten. Dies ist, weil es in Java nicht erlaubt ist, da Objekt die Basisklasse für alle Klassen ist und wir können nicht eine Klasse Ebene statische Methode und eine andere Instanz Methode mit derselben Signatur haben.

5) Wir können Java-Schnittstelle statische Methoden verwenden, um Utility-Klassen wie Sammlungen zu entfernen und alle seine statische Methoden in der entsprechenden Schnittstelle bewegen,    das wäre leicht zu finden und zu nutzen.

public class InterfaceExample implements exp1 {

    @Override
    public void method() {
        System.out.println("From method()");
    }

    public static void main(String[] args) {
        new InterfaceExample().method2();
        InterfaceExample.methodSta2();      //  <---------------------------    would not compile
        // methodSta1();                        //  <---------------------------    would not compile
        exp1.methodSta1();
    }

    static void methodSta2() {          //          <-- it compile successfully but it can't be overridden in child classes
        System.out.println("========= InterfaceExample :: from methodSta2() ======");
    }
}


interface exp1 {

    void method();
    //protected void method1();         //          <--      error
    //private void method2();           //          <--      error
    //static void methodSta1();         //          <--      error it require body in java 1.8

    static void methodSta1() {          //          <-- it compile successfully but it can't be overridden in child classes
        System.out.println("========= exp1:: from methodSta1() ======");
    }

    static void methodSta2() {          //          <-- it compile successfully but it can't be overridden in child classes
        System.out.println("========= exp1:: from methodSta2() ======");
    }

    default void method2() { System.out.println("---  exp1:: from method2() ---");}
    //synchronized default void method3() { System.out.println("---");}             // <-- Illegal modifier for the interface method method3; only public, abstract, default, static 
                                                                                // and strictfp are permitted
    //final default void method3() { System.out.println("---");} //             <--      error
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top