Bawiłem się modyfikatorami metodą statyczną i zauważyłem dziwne zachowanie.
Jak wiemy, metod statycznych nie można przesłonić, ponieważ są one skojarzone z klasą, a nie instancją.
Więc jeśli mam poniższy fragment, kompiluje się dobrze
//Snippet 1 - Compiles fine
public class A {
static void ts() {
}
}
class B extends A {
static void ts() {
}
}
Ale jeśli dołączę ostateczny modyfikator do metody statycznej w klasie A, kompilacja nie powiedzie się ts () w B nie może przesłonić ts () w A; nadpisana metoda jest statyczna ostateczna .
Dlaczego tak się dzieje, gdy metody statycznej nie można w ogóle zastąpić?
Odpowiedzi:
Metody statyczne nie mogą zostać zastąpione, ale można je ukryć.
ts()
Metoda B nie jest nadrzędne (nie podlega polimorfizmu)ts()
od A, ale będzie to ukryć. Jeśli zawołaszts()
B (NIEA.ts()
lubB.ts()
... po prostuts()
), zostanie wywołany ten z B, a nie A. Ponieważ nie jest to poddane polimorfizmowi, wywołaniets()
w A nigdy nie zostanie przekierowane do tego w B.Słowo kluczowe
final
wyłącza ukrywanie metody. Dlatego nie można ich ukryć, a próba zrobienia tego spowoduje błąd kompilatora.Mam nadzieję że to pomoże.
źródło
A#ts
jest dziedziczona, a taka metoda już istniejeB
, po prostu posiadanie dwóch metod z tą samą sygnaturą i innym modyfikatorem (final
) nie działałoby jako przeciążenie. Żałuję jednak, że nieTo nie jest do końca prawda. Przykładowy kod tak naprawdę oznacza, że metoda ts w B ukrywa metodę ts w A. Więc nie jest to do końca przesłanianie. Na Javaranch jest ładne wyjaśnienie.
źródło
Metody statyczne należą do klasy, a nie do instancji.
A.ts()
iB.ts()
zawsze będą to oddzielne metody.Prawdziwym problemem jest to, że Java umożliwia wywoływanie metod statycznych na obiekcie instancji. Metody statyczne z tym samym podpisem z klasy nadrzędnej są ukrywane, gdy są wywoływane z instancji podklasy. Nie możesz jednak przesłonić / ukryć ostatecznych metod .
Można by pomyśleć, że komunikat o błędzie użyje słowa ukrytego zamiast zastąpionego ...
źródło
Być może będziesz w stanie pomyśleć o ostatecznym zakończeniu metody statycznej, biorąc pod uwagę następujące kwestie:
Posiadanie następujących klas:
Teraz „poprawnym” sposobem na wywołanie tych metod byłoby
co spowoduje,
AB
ale możesz również wywołać metody w instancjach:co by też skutkowało
AB
.Rozważmy teraz następujące kwestie:
to by się wydrukowało
A
. To może cię zaskoczyć, ponieważ tak naprawdę masz przedmiot klasyB
. Ale ponieważ wywołujesz go z referencji typuA
, zadzwoniA.ts()
. Możesz wydrukowaćB
za pomocą następującego kodu:W obu przypadkach posiadany obiekt pochodzi z klasy
B
. Ale w zależności od wskaźnika, który wskazuje na obiekt, wywołasz metodę fromA
lub fromB
.Teraz powiedzmy, że jesteś twórcą klasy
A
i chcesz zezwolić na tworzenie podklas. Ale naprawdę chceszts()
, aby metoda , kiedykolwiek wywołana, nawet z podklasy, robiła to, co chcesz, a nie była ukryta przez wersję podklasy. Wtedy możesz to zrobićfinal
i zapobiec ukryciu go w podklasie. I możesz być pewien, że poniższy kod wywoła metodę z Twojej klasyA
:Ok, wprawdzie jest to w jakiś sposób skonstruowane, ale w niektórych przypadkach może to mieć sens.
Nie powinieneś wywoływać metod statycznych na instancjach, ale bezpośrednio na klasach - wtedy nie będziesz miał tego problemu. Na przykład IntelliJ IDEA wyświetli ostrzeżenie, jeśli wywołasz metodę statyczną na instancji, a także, jeśli sprawisz, że metoda statyczna zostanie ostateczna.
źródło
Metoda ts () w B nie przesłania metody ts () w A, jest po prostu inną metodą. Klasa B nie widzi metody ts () w A, ponieważ jest statyczna, dlatego może zadeklarować własną metodę o nazwie ts ().
Jeśli jednak metoda jest ostateczna, kompilator wykryje, że istnieje metoda ts () w A, której nie należy przesłonić w B.
źródło
Myślę, że błąd kompilacji był tutaj dość mylący. Nie powinno było powiedzieć „zastąpiona metoda jest statyczną ostateczną metodą”, ale zamiast tego powinna powiedzieć „zastąpiona metoda jest ostateczna”. Modyfikator statyczny nie ma tutaj znaczenia.
źródło
Metody statycznej nie można przesłonić w Javie, w przeciwieństwie do metod niestatycznych. Ale są dziedziczone jak statyczne i niestatyczne elementy członkowskie danych. Dlatego w klasie nadrzędnej nie można utworzyć metody niestatycznej o tej samej nazwie
Te
final
, zapewnia słów kluczowych, które organ specjalny sposób być prowadzone za każdym wywołanie metody. Teraz, jeśli w klasie potomnej zostanie utworzona metoda statyczna o tej samej nazwie i zostanie wykonane wywołanie metody, metoda w podklasie zostanie wykonana, co nie powinno mieć miejsca, jeśli final jest poprzedzony nazwą metody statycznej w klasie nadrzędnej . Stąd słowo kluczowe final ogranicza tworzenie metody o tej samej nazwie w klasie potomnej.źródło