2013-08-01 21 views
12

JVM decyduje, która metoda jest przeładowana w czasie kompilacji. Mam jeden przykład:W jaki sposób JVM znajduje metodę (parametr o najbliższym dopasowaniu) do wywołania w przypadku przeciążenia funkcji

public class MainClass{ 

    public static void go(Long n) {System.out.println("takes Long ");} 
    public static void go(Short n) {System.out.println("takes Short ");} 
    public static void go(int n) {System.out.println("takes int ");} 

    public static void main(String [] args) { 
    short y = 6; 
    long z = 7; 
    go(y); 
    go(z); 
    go((Short)y); 
    } 
} 

Według mojego rozeznania, należy wydrukować następujące:

takes Short 
takes Long 
takes Short 

... ale rzeczywisty wynik jest:

takes int 
takes Long 
takes Short 

Jednak jeśli mam następujące trzy funkcje:

public static void go(Integer n) {System.out.println("takes Integer");} 
public static void go(Long n) {System.out.println("takes Long ");} 
public static void go(Short n) {System.out.println("takes Short ");} 

... i nazwać go za pomocą:

int a= 10; and go(i); //output : takes Integer. 

... dlaczego tam jest jakaś różnica dla short i int?

+0

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.4 – kosa

+0

Możliwy duplikat http://stackoverflow.com/ q/6268157/2087187 – EProgrammerNotFound

Odpowiedz

18

Zobacz JLS Section 15.12.2, dla zasady kompilator następujący sposób określić, która metoda do wywołania. Kompilator zawsze wybiera najbardziej specyficzną metodę w przypadku przeciążenia metod:

Może być więcej niż jedna taka metoda, w takim przypadku wybrana jest najbardziej szczegółowa. Deskryptor (podpis i typ zwracany) najbardziej szczegółowej metody to taki, który jest używany w czasie wykonywania w celu przeprowadzenia wysyłki metody.

kompilator najpierw próbuje rozwiązać ten sposób bez bokserski Unboxing cytowany tam:

Pierwszy etap (§15.12.2.2) przeprowadza rozpoznawanie przeciążeniem nie dopuszczając bokserski lub rozpakowywanie konwersji lub użycie wywołania metody zmiennej aryt. Jeśli podczas tej fazy nie zostanie znaleziona żadna odpowiednia metoda, przetwarzanie będzie kontynuowane do drugiej fazy.

Podkreślam moją.

Tak w 1 ST Kod, ponieważ krótki mogą być wykorzystane jako argument dla parametru typu int.Kompilator nie użyje metody z parametrem Short, ponieważ wymaga to boksu. Podczas gdy w przypadku typu długi, ponieważ nie może być używany jako argument dla typu int, przechodzi on do boksowania go na Long. Pamiętaj: Poszerzenie jest preferowane w stosunku do Boxingu.

W twoim 2 nd, nie ma innego sposobu niż boksowanie int na Integer. Dlatego wywołuje metodę z parametrem Integer.

8

Maszyna wirtualna JVM nie znajduje go w ogóle. Kompilator ma. To wybiera najbardziej specyficzną metodę, zgodnie z przepisami JLS section 15.12.2.5:

Jeśli więcej niż jedna metoda członkiem jest zarówno dostępne i stosowane metody w inwokacji, konieczne jest, aby wybrać jedną, aby zapewnić deskryptor dla biegu czas wysyłki metody. Język programowania Java korzysta z reguły, że wybrana jest najbardziej szczegółowa metoda.

Nieformalną intuicją jest to, że jedna metoda jest bardziej szczegółowa od innej, jeśli jakiekolwiek wywołanie obsługiwane przez pierwszą metodę może zostać przekazane drugiej, bez błędu typu kompilacji.

... (pełne zasady) ...

+2

+1 nie tylko musi być identyczne, jak i typy parametrów, ale musi być również typem zwracanym. Jeśli A wywoła B i zmienisz typ zwracania metody w B bez ponownego kompilowania A, nie uda się znaleźć metody w czasie wykonywania. –

1

Ponieważ upcasting do int był w wersji 1.0 Java i auto-boxing został dodany w wersji 5.0. Zmiana zachowania naruszy kod napisany dla starszej wersji Java.

+0

To nie jest "upcasting" - to "konwersja poszerzająca". Ale w innym razie dobry punkt +1. –

+1

@MarkoTopolnik. Cóż, odpowiedź wydaje się być kopią wklejoną zaakceptowanej odpowiedzi z duplikatu opublikowanego dla tego pytania. Tak więc błąd jest w * Source *. lol;) –

+0

@RohitJain Ups, dzięki za sprawdzenie tego! I wiemy, co dostaje plagiat ... –

0

Poszerzenie następuje przed boksowaniem (jeśli występuje). Tak więc short stanie się int i wywoła te metody.

Poza tym, nie bezpośrednio związane z tym pytania, ale ciekawym punkcie: Nie można Box i poszerzyć tj short nie może stać Integer

0

Java szuka najbliższego meczu pierwszej kolejności. Stara się znaleźć następujące:

  1. Dokładne dopasowanie według typu
  2. Matching super klasy typu
  3. Konwersja do większej prymitywnego typu
  4. konwersji na auto zapakowane typu
  5. varargs