Dlaczego nie ma metod statycznych w interfejsach, ale pola statyczne i klasy wewnętrzne OK? [pre-Java8]

Zadano tu kilka pytań o to, dlaczego nie można zdefiniować statycznych metod w interfejsach, ale żadne z nich nie odnosi się do podstawowej niespójności: dlaczego można zdefiniować statyczne pola i statyczne typy wewnętrzne w interfejsie, ale nie metody statyczne?

Statyczne typy wewnętrzne może nie są sprawiedliwym porównaniem, ponieważ to tylko cukier składniowy generuje nową klasę, ale dlaczego pola, a nie metody?

Argumentem przeciwko metodom statycznym w interfejsach jest to, że łamie strategię rozdzielczości wirtualnej tabeli używaną przez JVM, ale czy nie powinno to mieć zastosowania w równym stopniu do pól statycznych, tzn. kompilator może ją po prostu wbudować?

Spójność jest tym, czego pragnę, a Java powinna albo nie obsługiwać żadnych statyk jakiejkolwiek formy w interfejsie, albo powinna być spójna i pozwalać na nie.

Author: skaffman, 2008-09-24

15 answers

Wprowadzono oficjalną propozycję , Aby zezwolić na statyczne metody w interfejsach Java 7. Propozycja ta jest realizowana w ramach projektu .

Osobiście uważam, że to świetny pomysł. Nie ma żadnych trudności technicznych w implementacji i jest to bardzo logiczna, rozsądna rzecz do zrobienia. Jest kilka propozycji w Project Coin, które mam nadzieję, że Nigdy nie staną się częścią języka Java, ale ten może oczyścić wiele API. Na przykład, na Collections Klasa posiada statyczne metody do manipulowania dowolną implementacją List; te mogą być zawarte w interfejsie List.

Update: W Java Posse Podcast #234, Joe D 'arcy krótko wspomniał o tej propozycji, mówiąc, że jest ona "złożona" i prawdopodobnie nie trafi do projektu Coin.


Update: chociaż nie udało im się stworzyć Project Coin dla Javy 7, Java 8 obsługuje funkcje statyczne W interfejsy.

 49
Author: erickson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 16:59:40

Pójdę z moją teorią zwierząt z tym jednym, który jest, że brak spójności w tym przypadku jest kwestią wygody, a nie projektowania lub konieczności, ponieważ nie słyszałem przekonującego argumentu, że to jeden z tych dwóch.

Statyczne pola są tam (a), ponieważ były tam w JDK 1.0, a wiele podejrzanych decyzji zostało podjętych w JDK 1.0, oraz (b) statyczne pola końcowe w interfejsach są najbliższą rzeczą, jaką java miała do stałych w tym czasie.

Statyczne klasy wewnętrzne w interfejsy były dozwolone, ponieważ to czysty cukier składniowy - Klasa wewnętrzna nie ma właściwie nic wspólnego z klasą nadrzędną.

Więc metody statyczne nie są dozwolone tylko dlatego, że nie ma przekonującego powodu, aby to zrobić; spójność nie jest wystarczająco przekonująca, aby zmienić status quo.

Oczywiście, może to być dozwolone w przyszłych wersjach JLS bez niszczenia czegokolwiek.

 39
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-15 12:45:37

Nie ma sensu deklarować statycznej metody w interfejsie. Nie można ich wykonać normalnym wywołaniem MyInterface.staticMethod(). (EDIT: od tego ostatniego zdania niektórzy mylą, nazywając MyClass.staticMethod () wykonuje dokładnie implementację staticMethod na MyClass, która jeśli MyClass jest interfejsem, nie może istnieć!) Jeśli wywoła się je przez podanie implementującej klasy MyImplementor.staticMethod() to musisz znać rzeczywistą klasę, więc nie ma znaczenia czy interfejs go Zawiera lub nie.

Co ważniejsze, metody statyczne nigdy nie są nadpisywane, a jeśli spróbujesz zrobić:

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

Reguły statyczne mówią, że musi zostać wykonana metoda zdefiniowana w zadeklarowanym typie var. Ponieważ jest to interfejs, jest to niemożliwe.

Można oczywiście zawsze usunąć słowo kluczowe statyczne z metody. Wszystko będzie dobrze. Może być konieczne stłumienie niektórych ostrzeżeń, jeśli jest wywoływana z metody instancji.

Aby odpowiedzieć na niektóre z komentarze poniżej, powód, dla którego nie można wykonać " result=MyInterface.staticMethod ()" polega na tym, że musiałaby wykonać wersję metody zdefiniowanej w MyInterface. Ale nie może być zdefiniowana wersja w mojej interfejsie, ponieważ jest to interfejs. Nie ma kodu z definicji.

 13
Author: DJClayworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-06 14:23:56

Celem interfejsów jest zdefiniowanie Umowy bez zapewnienia realizacji. Dlatego nie możesz mieć metod statycznych, ponieważ musiałyby one mieć implementację już w interfejsie, ponieważ nie możesz nadpisać metod statycznych. Jeśli chodzi o pola, dozwolone są tylko statyczne final fields, które są zasadniczo stałymi (w 1.5+ można również mieć enums w interfejsach). Stałe są tam, aby pomóc zdefiniować interfejs bez magicznych liczb.

BTW, nie ma potrzeby wyraźnie określa modyfikatory static final dla pól w interfejsach, ponieważ dozwolone są tylko statyczne pola końcowe.

 6
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 21:39:32

To jest stary wątek, ale to jest bardzo ważne pytanie dla wszystkich. Ponieważ zauważyłem to dzisiaj tylko dlatego staram się to wyjaśnić w czystszy sposób:

Głównym celem interfejsu jest dostarczenie czegoś, co jest niewykonalne, więc jeśli dostarczają

Dozwolone metody statyczne

Następnie możesz wywołać tę metodę używając interfaceename.staticMethodName () , ale jest to metoda nie implementowana i nie zawiera nic. Więc nie ma sensu Zezwalaj na metody statyczne. Dlatego w ogóle tego nie zapewniają.

Dozwolone są pola statyczne

Ponieważ pola nie są implementowalne, przez implementowalne mam na myśli, że nie można wykonać żadnej logicznej operacji w polu, można wykonać operację na polu. Więc nie zmieniasz zachowania pola, dlatego są one dozwolone.

Klasy wewnętrzne są dozwolone

Klasy wewnętrzne są dozwolone, ponieważ po kompilacji inny plik klasy wewnętrznej klasy jest tworzony say Interfaceename$InnerClassName.Klasa , więc w zasadzie dostarczasz implementację w różnych obiektach razem, ale nie w interfejsie. Tak więc implementacja w klasach wewnętrznych jest zapewniona.

Mam nadzieję, że to pomoże.

 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-11 21:33:50

Faktycznie czasami są powody, dla których ktoś może skorzystać z metod statycznych. Mogą być używane jako metody fabryczne dla klas implementujących interfejs. Na przykład z tego powodu mamy interfejs kolekcji i klasę kolekcji w openjdk. Są więc obejścia, jak zawsze - dostarcz innej klasie prywatny konstruktor, który będzie służył jako" przestrzeń nazw " dla metod statycznych.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-28 19:43:21

Przed Javą 5, powszechnym użyciem dla pól statycznych było:

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();
    }
}

Oznaczało to, że HtmlBuilder nie musiał kwalifikować każdej stałej, więc mógł używać OPENzamiast HtmlConstants.Otwórz

używanie narzędzi w ten sposób jest ostatecznie mylące.

Teraz w Javie 5 mamy import statycznej składni , aby osiągnąć ten sam efekt:

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

import static HtmlConstants.*;
public class HtmlBuilder { // no longer uses implements
    ...
}
 3
Author: toolkit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-31 23:50:57

Nie ma prawdziwego powodu, aby nie mieć statycznych metod w interfejsach, z wyjątkiem: projektanci języka Java nie chcieli tego w ten sposób. Z technicznego punktu widzenia byłoby sensowne, aby na to pozwolić. W końcu klasa abstrakcyjna też może je mieć. Zakładam, ale nie testowałem, że można "ręcznie" kod bajtowy, gdzie interfejs ma statyczną metodę i powinno IMHO działać bez problemów, aby wywołać metodę i / lub używać interfejsu jak zwykle.

 3
Author: Angel O'Sphere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-13 12:01:54

Często zastanawiam się, dlaczego statyczne metody w ogóle? Mają swoje zastosowania, ale metody na poziomie package / namespace prawdopodobnie obejmowałyby 80 metod statycznych.

 2
Author: Vasil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-19 17:02:43

Na myśl przychodzą dwa główne powody:

  1. Statyczne metody w Javie nie mogą być nadpisywane przez podklasy, a jest to znacznie większa sprawa dla metod niż statyczne pola. W praktyce nigdy nawet nie chciałem nadpisywać pola w podklasie, ale nadpisuję metody cały czas. Tak więc posiadanie metod statycznych uniemożliwia klasie implementującej interfejs dostarczanie własnej implementacji tej metody, co w dużej mierze podważa cel użycia interfejs.

  2. Interfejsy nie powinny mieć kodu; po to są klasy abstrakcyjne. Celem interfejsu jest umożliwienie mówienia o potencjalnie niepowiązanych obiektach, które mają określony zestaw metod. W rzeczywistości zapewnienie implementacji tych metod wykracza poza granice tego, jakie interfejsy mają być zamierzone.

 1
Author: Eli Courtwright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 19:25:51

Metody statyczne są powiązane z klasą. W Javie interfejs nie jest technicznie klasą, jest typem, ale nie klasą (stąd słowo kluczowe implementuje, a Interfejsy nie rozszerzają obiektu). Ponieważ interfejsy nie są klasami, nie mogą mieć metod statycznych, ponieważ nie ma rzeczywistej klasy, do której można by dołączyć.

Możesz wywołać nazwę interfejsu.klasy, aby uzyskać obiekt klasy odpowiadający interfejsowi, ale klasa klasy wyraźnie stwierdza, że reprezentuje klasy i interfejsy w Aplikacji Java. Jednak sam interfejs nie jest traktowany jako klasa, a zatem nie można dołączyć statycznej metody.

 1
Author: MetroidFan2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 17:38:21

Tylko statyczne pola końcowe mogą być zadeklarowane w interfejsie (podobnie jak metody, które są publiczne, nawet jeśli nie zawiera się słowa kluczowego "public", statyczne pola są "ostateczne" ze słowem kluczowym lub bez niego).

Są to tylko wartości i będą kopiowane dosłownie wszędzie tam, gdzie są używane podczas kompilacji, więc nigdy w rzeczywistości nie" wywołasz " statycznych pól w czasie wykonywania. Posiadanie statycznej metody nie miałoby takiej samej semantyki, ponieważ wiązałoby się z wywołaniem interfejsu bez implementacji, co Java nie pozwala.

 0
Author: cynicalman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-24 19:26:04

Powodem jest to, że wszystkie metody zdefiniowane w interfejsie są abstrakcyjne, niezależnie od tego, czy jawnie zadeklarujesz ten modyfikator. Abstrakcyjna metoda statyczna nie jest dopuszczalną kombinacją modyfikatorów, ponieważ metody statyczne nie mogą być nadpisywane.

Dlaczego interfejsy zezwalają na pola statyczne. Mam wrażenie, że należy to uznać za"cechę". Jedyną możliwością, jaką mogę sobie wyobrazić, byłoby grupowanie stałych, którymi implementacje interfejsu byłyby zainteresowane.

I zgadzam się, że spójność byłaby lepszym podejściem. Żadne statyczne elementy nie powinny być dozwolone w interfejsie.

 0
Author: laz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 15:04:44

Uważam, że statyczne metody mogą być dostępne bez tworzenia obiektu, a interfejs nie pozwala na tworzenie obiektu, co ogranicza programistom korzystanie z metod interfejsu bezpośrednio, a nie z jego zaimplementowanej klasy. Ale jeśli zdefiniujesz statyczną metodę w interfejsie, możesz uzyskać do niej bezpośredni dostęp bez jej implementacji. Dlatego metody statyczne nie są dozwolone w interfejsach. Nie sądzę, że konsekwencja powinna być problemem.

 0
Author: prerana gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-17 09:37:12

Statyczna metoda interfejsu Java 1.8 jest widoczna tylko dla metod interfejsu, jeśli usuniemy metodę methodSta1() z klasy InterfaceExample, nie będziemy mogli go użyć dla obiektu InterfaceExample. Jednak podobnie jak inne metody statyczne, możemy używać metod statycznych interfejsu używając nazwy klasy. Na przykład ważne oświadczenie będzie: EXP 1.methodSta1 ();

Więc Po spojrzeniu na poniższy przykład możemy powiedzieć : 1) statyczna metoda interfejsu Java jest częścią interfejsu, nie możemy jej używać do obiekty klasy implementacji.

2) statyczne metody interfejsu Java są dobre do dostarczania metod użytkowych, na przykład sprawdzania null, sortowania kolekcji ,logowania itp.

3) Java interface static method pomaga nam w zapewnieniu bezpieczeństwa, nie pozwalając klasom implementacyjnym (InterfaceExample) na ich nadpisywanie.

4) nie możemy zdefiniować statycznej metody interfejsu dla metod klasy obiektowej, otrzymamy błąd kompilatora jako "ta statyczna metoda nie może ukryć metody instancji przed obiektem". To to dlatego, że nie jest to dozwolone w Javie, ponieważ obiekt jest klasą bazową dla wszystkich klas i nie możemy mieć jednej statycznej metody na poziomie klasy i innej metody instancji z tym samym podpisem.

5) możemy użyć statycznych metod interfejsu java, aby usunąć klasy narzędzi, takie jak Kolekcje i przenieść wszystkie statyczne metody do odpowiedniego interfejsu, to byłoby łatwe do znalezienia i użycia.

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
}
 0
Author: Ashish Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 11:26:02