Dlaczego zmienne interfejsu są domyślnie statyczne i końcowe w Javie?
Dlaczego zmienne interfejsu są domyślnie statyczne i końcowe w Javie?
Odpowiedzi:
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.
static
modyfikatora 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 interface
nie może zostać utworzona bezpośrednio - nadal możesz mieć instancje klas, które implementują interface
i 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 final
oznacza.
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 !!!
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.
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.
( To nie jest filozoficzna odpowiedź, ale bardziej praktyczna ). Wymóg dotyczący static
modyfikatora 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 interface
pola 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 interface
właściwość nie stała się jawnie final
przez 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, Actionable
zmieni 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 NuclearAction
może mieć wpływ inna klasa CleanAction
, gdy performAction()
zostanie ona wywołana po CleanAction
wykonaniu 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 interface
użyje tych zmiennych, muszą one być domyślnie takie final
.
Ponieważ wszystko inne jest częścią implementacji, a interfejsy nie mogą zawierać żadnej implementacji.
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.
static final
przed zmienną, która faktycznie jest statyczna i końcowa.
statyczny - ponieważ interfejs nie może mieć żadnej instancji. i na koniec - ponieważ nie musimy go zmieniać.
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
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
Interfejs to umowa między dwiema stronami, która jest niezmienna, wykuta w kamieniu, a więc ostateczna. Zobacz Projekt na podstawie umowy .
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.
W Java
interfejsie 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 final
której różni się od zmiennej instancji.
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.
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.
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));
}
}