2011-02-10 13 views
26

mam szybki i straighforward pytanie:Polimorfizm i metoda przeciążenia

mam tę prostą klasę:

public class A 
{ 
    public void m(Object o) 
    { 
     System.out.println("m with Object called"); 
    } 

    public void m(Number n) 
    { 
     System.out.println("m with Number called"); 
    } 
    public static void main(String[] args) 
    { 
     A a = new A(); 
     // why will m(Number) be called? 
     a.m(null); 
    } 
} 

UPDATE: faktycznie jest metoda z liczba rzeczywiście miano. Przepraszam za zamieszanie.

Jeśli zadzwonię do a.m (null), wywołuje on metodę z parametrem Number.

Moje pytanie brzmi: dlaczego tak jest? gdzie w specyfikacji języka Java jest to określone?

+1

... ponieważ 'null' nie jest obiektem' Number', przez co trafia do bardziej uogólnionego zasobnika 'Object'. – limc

+5

To zabawne, ponieważ na moim komputerze (uruchomionym na zaćmieniu) domyślnie jest to metoda numer –

+1

+1 interesujące pytanie –

Odpowiedz

27

Po pierwsze, w rzeczywistości wywołuje m(Number).

Dzieje się tak dlatego, że obie metody są zastosowanie, ale m(Number) jest najbardziej specyficzną metodą, ponieważ każdy argument m(Number) mogą być przekazywane do m(Object), ale nie na odwrót.

Jeśli zastąpić m(Object) przez m(String) (lub dodać innej metody takie jak m(Date)), kompilator będzie zgłosić niejasności, ponieważ nie można zidentyfikować w sposób najbardziej szczegółowy sposób.

Patrz sekcja Choosing the Most Specific Method w specyfikacji Java.

+2

OK, teraz, gdy uruchomiłem kod przykładowy, widzę to również. Ma również sens, że po dodaniu m (Date n) {...} otrzymałem błąd: "metoda m (Object) jest niejednoznaczna dla typu" – David

0

Object to domyślny typ w Javie. Jeśli byłaby metodę m(Object o) do m(String o) będziesz miał błąd kompilacji czas mówiąc, że wezwanie m(null) jest niejednoznaczny, ponieważ Java nie można określić, która klasa między String i Number domyślnych do null

Poza tym, między m(Object o) i m(Number o), nazywając m(null) zadzwoni pod numer m(Number o), ponieważ jest to najbardziej wyspecjalizowana metoda. Musisz odrzucić null w Object (lub cokolwiek innego niż instancję Number) w przeciwnym razie.

a.m((String) null); 
+0

null nie ma typu i wywołuje m (numer) –

+0

dobrze .. formalnie istnieje typ zerowy i jest to podtyp wszystkich typów referencji. dość dziwne. – irreputable

12
  1. To nie jest polimorfizm ani przesłonięcie. Jest to metoda polegająca na przeciążeniu .
  2. Przetestowałem to i wywoływana jest określona metoda (nie m (Obiekt)) i zgodnie ze specyfikacją zawsze wywoływana jest określona metoda. Which overload will get selected for null in Java?
+2

+1 dla zauważenia różnicy między nadpisaniem a przeciążeniem –

+0

+1 dla podkreślenia, że ​​jest to przeciążenie, –

1

Moje 2 centy. Metoda z argumentem Liczba jest tą, która jest wywoływana, ponieważ liczba powiększa obiekt. Miałem podobną sytuację w przeszłości, zastąpiłem metodę i wstawiłem Component zamiast JComponent (przez pomyłkę). Zajęło mi tydzień odkrycie, dlaczego moja metoda nigdy nie została wywołana. Rozumiem, że jeśli istnieje jakiś związek dziedziczenia między przeciążonymi metodami, JVM dopasowuje najpierw głębszy w hierarchii klas.

7

inny, powiązany kwestia, aby myśleć o:

public static void main(String[] args) 
{ 
    A a = new A(); 
    Object n = new Integer(1); 
    a.m(n); // which method will be called? 
} 
+0

"mz obiektem o nazwie" zostanie wywołany, ale nie wiem dlaczego. Czy ktoś może wyjaśnić? Intuicyjnie pomyślałem, że "mz Numerem" zostanie wydrukowane, ale ... noooooo. – IsenGrim

0

Jaguar, According to the Java Specifications, tak, że jest to obiekt. Tak więc metoda wybrana dla a.m (true) w głównych ośrodkach na typ parametru Object.

logiczna jest zdefiniowane w java.lang.Boolean ilość jest zdefiniowana w Java.lang.Number

(zarówno rozszerzyć przedmiot)

Coders Rhyme książka: "Kiedy w Vex, odwoływać się widowisko"