Dlaczego zmienne interfejsu są domyślnie statyczne i końcowe?


274

Dlaczego zmienne interfejsu są domyślnie statyczne i końcowe w Javie?


41
Nie powinieneś umieszczać żadnych zmiennych w interfejsach.
cherouvim

34
Ponieważ interfejsy definiują umowy, które można realizować na różne sposoby. Wartością zmiennej jest implementacja.
cherouvim

10
Z pewnością możemy, gdy wiemy, że wszystkie klasy implementujące interfejs mają pewne stałe zmienne (na przykład nazwy pól).
Aniket Thakur,

Czy dobrym pomysłem jest uczynienie zmiennej w klasie instancji interfejsu implementowanego przez klasę? Już to słyszałem.
Doug Hauf

Interfejsy w Javie są zgodne z zasadą ACID, końcową ze względu na normalizację w C. @cherouvim Typem zmiennej jest implementacja, zmienna musi zostać zadeklarowana z wartością lub bez, a definicją zmiennej jest wartość. Jeśli zmienisz wartość zmiennej, to nie jest ona ponowna implementacja, to jej redefinicja.
Ponury

Odpowiedzi:


264

Z projektu FAQ interfejsu Java autorstwa Philipa Shawa:

Zmienne interfejsowe są statyczne, ponieważ interfejsów Java nie można tworzyć samodzielnie; wartość zmiennej musi być przypisana w kontekście statycznym, w którym nie istnieje żadna instancja. Ostateczny modyfikator zapewnia, że ​​wartość przypisana do zmiennej interfejsu jest prawdziwą stałą, której nie można ponownie przypisać kodem programu.

źródło


39
Zauważ, że klasy abstrakcyjne nie mogą być tworzone „same w sobie” ani te, i te mogą mieć zmienne instancji.
macias

18
To wyjaśnienie staticmodyfikatora jest całkowicie fałszywe. Zmienne instancji publicznej klasy są częścią jej interfejsu i nie ma powodu, dla którego nie powinny być abstrakcyjne w Javie interface, podobnie jak metody instancji. Nie ma znaczenia, że ​​Java interfacenie może zostać utworzona bezpośrednio - nadal możesz mieć instancje klas, które implementują interfacei rozsądne jest wymaganie, aby miały one określoną zmienną instancji publicznej. Jeśli chodzi o tę część final, to wcale nie oferuje wyjaśnienia - po prostu opisuje, co finaloznacza.
pirokrastyka

3
Powyższy cytat jest lepszy w kontekście. Powodem jest to, że „zmienne interfejsu mają być stałymi Java”. Cytat właśnie wyjaśniał, dlaczego taka stała byłaby statyczna i ostateczna. To prawda, ale prawdziwe pytanie brzmi: dlaczego zmienne nie są dozwolone jako część rzeczywistego interfejsu (tj. Określanie nazw i typów członków nieprywatnych, które muszą wystąpić w klasie implementującej). Gdyby chcieli specjalnych „stałych interfejsu”, mogliby zastosować nową składnię lub po prostu zdecydować, że dowolne zmienne faktycznie zdefiniowane w interfejsie są stałymi interfejsu.
pirokrastyka

6
Interfejsy nie mogą mieć zmiennych instancji, aby uniknąć wielokrotnego dziedziczenia problemów stanu. Zobacz docs.oracle.com/javase/tutorial/java/IandI/… . Klasa nie może rozszerzyć więcej niż jednej klasy z tego samego powodu.
denis

1
W jaki sposób wprowadzane są metody domyślne i mają one instancję, ale zmienna instancji nie jest obsługiwana ...
M.kazem Akhgary

41

Ponieważ interfejs nie ma bezpośredniego obiektu, jedynym sposobem na dostęp do nich jest użycie klasy / interfejsu i dlatego jeśli zmienna interfejsu istnieje, powinna być statyczna, w przeciwnym razie nie będzie w ogóle dostępna dla świata zewnętrznego. Teraz, ponieważ jest statyczny, może przechowywać tylko jedną wartość, a każda klasa, która go implementuje, może go zmienić, a zatem będzie cały bałagan.

Dlatego jeśli w ogóle istnieje zmienna interfejsu, będzie ona domyślnie statyczna, końcowa i oczywiście publiczna !!!


Oczywiście zmienna instancji byłaby dostępna, gdyby była dozwolona w Javie interface. Klasa implementuje interfejs, deklarując zmienną instancji (zgodnie z wymaganiami interfejsu). Jego konstruktor (lub inna metoda) ustawia zmienną instancji. Po wystąpieniu instancji klasy będziesz mieć dostęp do jej zmiennej instancji.
pirokrastyka

Java pozwala na istnienie w interfejsie metod statycznych z ciałami. Mogą one uzyskać dostęp do zmiennych statycznych. Po prostu nie mogą ich zmienić, co oznacza, że ​​funkcje statyczne nie mogą przechowywać żadnych danych
simpleuser

36

public : dla dostępności we wszystkich klasach, podobnie jak metody obecne w interfejsie

statyczny : ponieważ interfejs nie może mieć obiektu, nazwa_interfejsu.nazwa_zmiennej może być używana do odwoływania się do niego lub bezpośrednio do zmiennejName w klasie implementującej go.

końcowy : aby stały się stałymi. Jeśli 2 klasy zaimplementują ten sam interfejs i dacie obu z nich prawo do zmiany wartości, wystąpi konflikt w bieżącej wartości zmiennej var, dlatego dozwolona jest tylko jednorazowa inicjalizacja.

Ponadto wszystkie te modyfikatory są niejawne dla interfejsu, tak naprawdę nie trzeba określać żadnego z nich.


15

( To nie jest filozoficzna odpowiedź, ale bardziej praktyczna ). Wymóg dotyczący staticmodyfikatora jest oczywisty, na co odpowiedzieli inni. Zasadniczo, ponieważ interfejsów nie można utworzyć, jedynym sposobem na uzyskanie dostępu do jego pól jest uczynienie ich polami klasy static.

Powodem, dla którego interfacepola stają się automatycznie final(stałe), jest zapobieganie przypadkowej zmianie wartości zmiennej interfejsu przez różne implementacje, która może przypadkowo wpłynąć na zachowanie innych implementacji. Wyobraź sobie poniższy scenariusz, w którym interfacewłaściwość nie stała się jawnie finalprzez Javę:

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!!!
        }
    }
}

Teraz zastanów się, co by się stało, gdyby inna klasa, która implementuje, Actionablezmieni stan zmiennej interfejsu:

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

Jeśli klasy te są ładowane w ramach jednej maszyny JVM przez moduł ładujący klasy, to na działanie NuclearActionmoże mieć wpływ inna klasa CleanAction, gdy performAction()zostanie ona wywołana po CleanActionwykonaniu jej (w tym samym wątku lub w inny sposób), co w tym przypadku może być katastrofalne (to znaczy semantycznie).

Ponieważ nie wiemy, w jaki sposób każda implementacja an interfaceużyje tych zmiennych, muszą one być domyślnie takie final.


9

Ponieważ wszystko inne jest częścią implementacji, a interfejsy nie mogą zawierać żadnej implementacji.


1
to jaki jest powód finału.
Jothi,

7
Wskazać, że jest to stała. Java nie ma słowa kluczowego const. static static to sposób deklarowania stałych.
Amir Afghani,

5
Od wersji Java 8 mogą zawierać implementację, ale zdecydowanie nie zaleca się jej używania, jeśli nie jest wymagana kompatybilność backwarts. :)
codepleb

6
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?
    }
}

Oto rozwiązanie.

System.out.println(A.x); // done

Myślę, że jest to jedyny powód, dla którego zmienne interfejsu są statyczne.

Nie deklaruj zmiennych w interfejsie.


3
W rzeczywistości bez specyfikacji „Axe” nawet się nie skompiluje ”, więc w rzeczywistości można bezpiecznie używać zmiennych (które domyślnie są publicznie statyczne, końcowe) w interfejsach
Marco

Nie zgadzam się z odpowiedzią, ponieważ @Marco powiedział, że nawet się nie skompiluje. Do tej pory nie znalazłem żadnej innej wady, być może po prostu nie widzisz napisanej static finalprzed zmienną, która faktycznie jest statyczna i końcowa.
Micer

5

statyczny - ponieważ interfejs nie może mieć żadnej instancji. i na koniec - ponieważ nie musimy go zmieniać.


15
„nie potrzebujemy” == „nie wolno nam”, nie mieszaj znaczeń.
peterh - Przywróć Monikę

3

ponieważ:

Static : ponieważ nie możemy mieć obiektów interfejsów, dlatego powinniśmy unikać używania zmiennych składowych na poziomie obiektu i powinniśmy używać zmiennych na poziomie klasy, tj. statycznych.

Final : abyśmy nie mieli niejednoznacznych wartości dla zmiennych (problem z diamentem - wielokrotne dziedziczenie).

A zgodnie z interfejsem dokumentacji jest to umowa, a nie wdrożenie.

Numer referencyjny: Abhishek Jain za odpowiedź na Quora


2

Java nie zezwala na zmienne abstrakcyjne i / lub definicje konstruktorów w interfejsach. Rozwiązanie: wystarczy zawiesić klasę abstrakcyjną między interfejsem a implementacją, która rozszerza jedynie klasę abstrakcyjną w następujący sposób:

 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

 }

Możesz także użyć klasy abstrakcyjnej bez interfejsu, jeśli masz pewność, że nie chcesz jej później implementować wraz z innymi interfejsami. Pamiętaj, że nie możesz utworzyć instancji klasy abstrakcyjnej, MUSISZ ją najpierw rozszerzyć.

(Słowo kluczowe „chroniony” oznacza, że ​​tylko klasy rozszerzone mogą uzyskać dostęp do tych metod i zmiennych).

spyro



1

Interfejs: obsługa wymagań systemowych.

W interfejsie zmienne są domyślnie przypisywane przez publiczny, statyczny, końcowy modyfikator dostępu. Ponieważ :

public: zdarza się czasem, że interfejs może zostać umieszczony w innym pakiecie. Musi więc uzyskać dostęp do zmiennej z dowolnego miejsca w projekcie.

statyczny: Jako taka niekompletna klasa nie może utworzyć obiektu. Tak więc w projekcie musimy uzyskać dostęp do zmiennej bez obiektu, abyśmy mogli uzyskać dostęp za pomocąinterface_filename.variable_name

końcowy: Załóżmy, że jeden interfejs implementuje wiele klas, a wszystkie klasy próbują uzyskać dostęp do zmiennej interfejsu i zaktualizować ją. Prowadzi to do niespójności zmiany danych i wpływa na każdą inną klasę. Musi więc zadeklarować modyfikator dostępu za pomocą finału.


0

W Javainterfejsie nie można zadeklarować żadnych zmiennych instancji. Użycie zmiennej zadeklarowanej w interfejsie jako zmiennej instancji zwróci błąd czasu kompilacji.

Możesz zadeklarować zmienną stałą, używając static finalktórej różni się od zmiennej instancji.


To jest po prostu źle. Kompilator nie będzie narzekał, chyba że uczynisz go prywatnym lub chronionym. Pod maską, jak już wspomnieli inni, są konwertowane na publiczny statyczny finał. I myślę, że to dość oczywiste, dlaczego. Ponieważ interfejs ma dyktować zachowanie, a nie stan.
Mikayil Abdullayev

0

Interfejs może być zaimplementowany przez dowolną klasę, a jeśli ta wartość zostanie zmieniona przez jedną z klas implementujących, to wprowadzą w błąd inne klasy implementujące. Interfejs jest w zasadzie odniesieniem do połączenia dwóch skorelowanych, ale różnych jednostek. Dlatego z tego powodu deklarująca zmienna wewnątrz interfejsu będzie domyślnie ostateczna, a także statyczna, ponieważ interfejs nie może zostać utworzony.


0

Pomyśl o aplikacji internetowej, w której interfejs jest zdefiniowany, a inne klasy go implementują. Ponieważ nie możesz utworzyć instancji interfejsu w celu uzyskania dostępu do zmiennych, musisz mieć statyczne słowo kluczowe. Ponieważ jest statyczna, każda zmiana wartości będzie odzwierciedlać inne instancje, które ją zaimplementowały. Aby temu zapobiec, definiujemy je jako ostateczne.


0

Wypróbowana w Eclipse zmienna w interfejsie jest domyślnie ostateczna, więc nie można jej zmienić. W porównaniu z klasą nadrzędną zmienne są zdecydowanie zmienne. Czemu? Z mojego punktu widzenia zmienna w klasie jest atrybutem, który zostanie odziedziczony przez dzieci, a dzieci mogą je zmieniać zgodnie z ich rzeczywistą potrzebą. Przeciwnie, interfejs definiuje tylko zachowanie, a nie atrybut. Jedynym powodem wprowadzenia zmiennych w interfejsie jest użycie ich jako stałych związanych z tym interfejsem. Chociaż nie jest to dobra praktyka według następującego fragmentu:

„Umieszczanie stałych w interfejsie było popularną techniką na początku Java, ale obecnie wielu uważa to za niesmaczne użycie interfejsów, ponieważ interfejsy powinny obsługiwać usługi świadczone przez obiekt, a nie jego dane. przez klasę są zazwyczaj szczegółami implementacji, ale umieszczenie ich w interfejsie promuje je do publicznego interfejsu API klasy ”.

Próbowałem też ustawić statycznie, albo nie robi żadnej różnicy. Kod jest jak poniżej:

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));
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.