Dlaczego wszystkie pola w interfejsie są niejawnie statyczne i ostateczne?

100

Próbuję tylko zrozumieć, dlaczego wszystkie pola zdefiniowane w interfejsie są niejawnie statici final. Pomysł utrzymywania pól staticma dla mnie sens, ponieważ nie możesz mieć obiektów interfejsu, ale dlaczego one są final(domyślnie)?

Czy ktoś wie, dlaczego projektanci Java zdecydowali się na tworzenie pól w interfejsie statici final?

peakit
źródło
Dla mojej uwagi: jest statyczny, ponieważ pola interfejsu nie staną się częścią obiektu, który go implementuje.
Deszcz

Odpowiedzi:

126

Interfejs nie może mieć zachowania ani stanu, ponieważ ma określać tylko kontrakt interakcji, bez szczegółów implementacji. Brak zachowania jest wymuszany przez niedopuszczenie do treści metod / konstruktorów lub bloków inicjujących statyczne / instancje. „Brak stanu” jest wymuszane przez zezwolenie tylko na statyczne pola końcowe. Dlatego klasa może mieć stan (stan statyczny), ale stan instancji nie jest wywnioskowany przez interfejs.

BTW: Stała w Javie jest definiowana przez statyczne pole końcowe (i zgodnie z konwencją nazwa używa UPPER_CASE_AND_UNDERSCORES).

Adriaan Koster
źródło
54
Niekoniecznie jest prawdą, że końcowe pola są stałymi; jest to gwarantowane tylko dla typów pierwotnych. Ogólnie rzecz biorąc, ostatnie słowo kluczowe oznacza jedynie, że lokalizacja pamięci nie ulegnie zmianie.
Pojawia się
8
Nie powiedziałem, że pola końcowe są stałymi, po prostu stałe są polami końcowymi. Zauważ, że dozwolone jest umieszczenie w interfejsie nieprymitywnego statycznego pola końcowego. Mimo że zawartość tego pola może się zmienić, odniesienie do niego jest stałe.
Adriaan Koster
1
@AdriaanKoster Powiedziałeś dokładnie, że ostatnie pole jest stałe: Żaden stan nie jest wymuszany tylko przez dopuszczanie stałych. - z tego zdania wynika, że ​​wszystkie końcowe pola są stałe. Możesz spróbować dalej spierać się o słowa, których użyłeś, ale oczywiście twoje stwierdzenie jest co najmniej mylące.
Tomáš Zato - Przywróć Monikę
2
To musi być mój zanikający intelekt, ale po sześciu latach patrzenia na tę odpowiedź, która jest moją najlepszą odpowiedzią, nadal nie rozumiem uwag. Zaproponuj inne sformułowanie, ponieważ nie widzę nic złego.
Adriaan Koster
Projektanci Java mogli chcieć uczynić interfejs bezstanowym, ale nie udało im się, ponieważ pole instancji może być modyfikowalną klasą. Zamiast przyznać, że się nie powiodło, wybierają wymuszenie na polach instancji static final, które są tak bliskie rzeczywistemu (rzeczywistemu C / C ++), constjak można uzyskać w Javie. Niestety jest to dorozumiane i może prowadzić do nieporozumień dla osób niebędących ekspertami. (Właśnie zdałem sobie sprawę, że tak jest, staticponieważ zauważyłem niezamierzone zachowanie. Dowiedziałem się, że pochodzą one finaltylko z tej odpowiedzi.)
not-a-user
27

Powód istnienia final

Dowolne implementacje mogą zmieniać wartość pól, jeśli nie są zdefiniowane jako ostateczne. Wtedy staną się częścią realizacji. Interfejs to czysta specyfikacja bez żadnej implementacji.

Powód istnienia static

Jeśli są statyczne, to należą do interfejsu, a nie do obiektu ani do typu obiektu w czasie wykonywania.

Gurpreet singh sidhuu
źródło
18

W tym miejscu znajduje się kilka punktów:

Tylko dlatego, że pola w interfejsie są niejawnie statyczne final, nie oznacza, że ​​muszą być stałymi czasu kompilacji, a nawet niezmiennymi. Możesz zdefiniować np

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(Pamiętaj, że zrobienie tego wewnątrz definicji adnotacji może zmylić javac , w związku z faktem, że powyższe faktycznie kompiluje się do statycznego inicjatora).

Ponadto powód tego ograniczenia jest bardziej stylistyczny niż techniczny i wiele osób chciałoby, aby było ono zrelaksowane .

Jesse Glick
źródło
9

Pola muszą być statyczne, ponieważ nie mogą być abstrakcyjne (podobnie jak metody). Ponieważ nie mogą być abstrakcyjne, osoby wdrażające nie będą w stanie logicznie zapewnić różnych implementacji pól.

Myślę, że pola muszą być ostateczne, ponieważ pola mogą być dostępne dla wielu różnych implementatorów, co pozwala na ich zmianę, może być problematyczne (ponieważ synchronizacja). Również, aby uniknąć ponownego wdrożenia (ukrycia).

Tylko moja myśl.

NawaMan
źródło
NawMan, twoje wyjaśnienie „Pola muszą być statyczne…” nie ma większego sensu. Ale miałeś rację co do "Pola muszą być ostateczne ..."
szczyt
1
Nie sądzę, żeby miał rację co do powodu, dla którego pola muszą być ostateczne. Umożliwienie różnym realizatorom zmiany pola nie jest problematyczne, ponieważ w przeciwnym razie dziedziczenie byłoby problematyczne. Pola muszą być ostateczne, jak powiedział Adriaan, ponieważ interfejs jest i powinien być bezpaństwowy. Interfejs ze stanem powinien być w zasadzie klasą abstrakcyjną.
Axelle Ziegler
Jeśli masz public staticpole, którego nie ma final, findbugs będzie narzekać (słusznie!).
Tom Hawtin - tackline
2

Uważam, że wymóg, aby pola były ostateczne, był zbyt restrykcyjny i błędem projektantów języka Java. Zdarzają się sytuacje, gdy np. Przy obsłudze drzewa trzeba ustawić w implementacji stałe, które są wymagane do wykonywania operacji na obiekcie typu interfejs. Wybór ścieżki kodu w klasie implementującej jest kludge. Obejście, którego używam, to zdefiniowanie funkcji interfejsu i zaimplementowanie jej, zwracając literał:

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

Jednak użycie tej składni byłoby prostsze, jaśniejsze i mniej podatne na nieprawidłową implementację:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}
Carl Klapper
źródło
Wydaje się, że bardziej narzekasz, że pola są statyczne niż ostateczne.
Daniel Yankowsky
0

Specyfikacja, kontrakty ... Instrukcja maszynowa dla dostępu do pola używa adresu obiektu plus przesunięcie pola. Ponieważ klasy mogą implementować wiele interfejsów, nie ma możliwości, aby pole interfejsu innego niż końcowe miało takie samo przesunięcie we wszystkich klasach rozszerzających ten interfejs. Dlatego też musi być zaimplementowany inny mechanizm dostępu do pola: dwa dostępy do pamięci (pobranie offsetu pola, pobranie wartości pola) zamiast jednego plus utrzymanie rodzaju wirtualnej tablicy pól (odpowiednik wirtualnej tabeli metod). Chyba po prostu nie chcieli komplikować jvm pod kątem funkcjonalności, którą można łatwo zasymulować za pomocą istniejących rzeczy (metod).

W scali możemy mieć pola w interfejsach, chociaż wewnętrznie są one zaimplementowane tak, jak wyjaśniłem powyżej (jako metody).

Jarosław
źródło
-1

static:

Wszystko (zmienna lub metoda), która jest staticw Javie, może być wywołane jako Classname.variablenamelub Classname.methodnamelub bezpośrednio. Nie jest obowiązkowe wywoływanie go tylko przy użyciu nazwy obiektu.

W interfejsie obiekty nie mogą być deklarowane i staticumożliwia wywoływanie zmiennych tylko poprzez nazwę klasy bez konieczności podawania nazwy obiektu.

final:

Pomaga utrzymać stałą wartość zmiennej, ponieważ nie można jej przesłonić w jej podklasach.

Sabika
źródło