2010-09-09 4 views
7

Próbka 1:Dlaczego te dwie próbki kodu dają różne wyniki?

class Animal { 
    public static void saySomething() { System.out.print(" Gurrr!"); 
    } 
} 
class Cow extends Animal { 
    public static void saySomething() { 
    System.out.print(" Moo!"); 
    } 
    public static void main(String [] args) { 
     Animal [] animals = {new Animal(), new Cow()}; 
     for(Animal a : animals) { 
      a.saySomething(); 
     } 
     new Cow().saySomething(); 
    } 
} 

wyjściowa wynosi:

Gurrr! Gurrr! Moo! 

Próbka 2:

class Animal { 
    public void saySomething() { System.out.print(" Gurrr!"); 
    } 
} 
class Cow extends Animal { 
    public void saySomething() { 
    System.out.print(" Moo!"); 
    } 
    public static void main(String [] args) { 
     Animal [] animals = {new Animal(), new Cow()}; 
     for(Animal a : animals) { 
      a.saySomething(); 
     } 
     new Cow().saySomething(); 
    } 
} 

wyjściowa:

Gurrr! Moo! Moo! 

ja po prostu nie rozumiem, dlaczego czyni saySomething nie-stat ic powoduje drugie wywołanie, mówiąc: Coś wywołuje wersję Cow zamiast wersji Animal. Rozumiem, że w obu przypadkach wynik będzie wynosił Gurrr! Moo! Moo!.

+0

"Specyfikacja języka Java mówi tak" to naprawdę wszystko. Dlaczego możesz wywołać metodę statyczną z takiego odniesienia do instancji, jak na początku, to prawdziwa dziwność. Ale jest już co najmniej jeden ogromny wątek wiki społeczności :) – Affe

Odpowiedz

1

Metody statyczne są związane z ich klasą podczas kompilacji i nie można ich używać polimorficznie. Kiedy deklarujesz "statyczną" metodę na Zwierzęciu, jest ona na zawsze związana z klasą Zwierząt i nie może być nadpisana. Metody statyczne są powiązane z obiektem klasy, a nie z instancją klasy.

Metody regularne są wiązane w czasie wykonywania, więc JVM może sprawdzić twoje wezwanie do "saySomething" i spróbować ustalić, czy omijasz podklasę Animal, a jeśli tak, to nadpisał metodę saySomething(). Normalne metody są związane z instancją obiektu, a nie z klasą.

Jest to również, dlaczego nigdy nie można to zrobić:

class Animal 
{ 
    public abstract static void saySomething(); 
} 

ponieważ „statycznych” oznacza „związany w czasie kompilacji”, nie ma to sens czegoś być statyczny i abstrakcyjny.

7

Po wywołaniu saySomething() na zwierzęciu, rzeczywisty typ zwierzęcia nie jest liczony, ponieważ saySomething() jest statyczny.

Animal cow = new Cow(); 
cow.saySomething(); 

jest taka sama jak

Animal.saySomething(); 

przykładu na trasę:

Gdy odniesienie docelowa jest obliczana i następnie odrzucono, ponieważ tryb wywołanie jest statyczny, odniesienie jest nie sprawdzono, czy jest zerowy:

class Test { 
    static void mountain() { 
     System.out.println("Monadnock"); 
    } 
    static Test favorite(){ 
     System.out.print("Mount "); 
     return null; 
    } 
    public static void main(String[] args) { 
     favorite().mountain(); 
    } 

}

która drukuje:
Góra Monadnock
Oto ulubiony zwraca null, jeszcze nie NullPointerException zostanie zgłoszony.


Zasoby:

na ten sam temat:

+1

Nigdy nie rozumiałem, dlaczego Java pozwala na wywołanie metody statycznej poprzez odwołanie do obiektu. Nie jest to konieczne i prowadzi do zamieszania w ten sposób. – erickson

+0

Uzgodnione. C++ też to umożliwia. Domyślam się, że to po prostu ułatwia pisarzowi kompilatorowi zezwolenie na ten rodzaj dostępu. –

+0

Cóż, próbowałem to obronić tutaj: http://stackoverflow.com/questions/3610309/java-static-confusion/ –

3

Można nie nadpisywania statyczne metody z tym samym podpisem w podklasach, tylko hide im.

przypadku metod klasy system wykonawcze wywołuje metodę określoną w rodzaju kompilacji odniesienia w którym sposób jest nazywany. Na przykład metody, środowisko wykonawcze wywołuje metodę zdefiniowaną w środowisku wykonawczym odwołania o nazwie, w której wywoływana jest metoda.

http://life.csu.edu.au/java-tut/java/javaOO/override.html

3

Niektóre ze znanych Nadrzędne "pułapek"

  • metody statyczne nie może być przesłonięta
  • metody prywatne nie może być przesłonięta

Wyjaśnia to wyjście.

1

Metody statyczne są powiązane z "klasą", a nie "instancją" obiektu. Odkąd mówimy o "Zwierzę" i wywołujemy metodę statyczną saySomething(). Zawsze będzie nawiązywać połączenie z "Zwierzęciem", chyba że odnosisz się do Krowy.