Jak wspomniano wcześniej, rozpoznawanie przeciążenia jest wykonywane w czasie kompilacji.
Java Puzzlers ma na to dobry przykład:
Zagadka 46: Przypadek zagubionego konstruktora
Ta łamigłówka przedstawia dwóch konstruktorów Mylących. Główna metoda wywołuje konstruktora, ale który? Wynik programu zależy od odpowiedzi. Co program drukuje, czy w ogóle jest to legalne?
public class Confusing {
private Confusing(Object o) {
System.out.println("Object");
}
private Confusing(double[] dArray) {
System.out.println("double array");
}
public static void main(String[] args) {
new Confusing(null);
}
}
Rozwiązanie 46: Przypadek mylącego konstruktora
... Proces rozwiązywania problemów w Javie przebiega w dwóch fazach. Pierwsza faza wybiera wszystkie metody lub konstruktory, które są dostępne i mają zastosowanie. Druga faza wybiera najbardziej szczegółowe metody lub konstruktory wybrane w pierwszej fazie. Jedna metoda lub konstruktor jest mniej specyficzna niż inna, jeśli może akceptować parametry przekazane do drugiej [JLS 15.12.2.5].
W naszym programie oba konstruktory są dostępne i mają zastosowanie. Konstruktor
Confusing (Object) akceptuje każdy parametr przekazany do Confusing (double []) , więc
Confusing (Object) jest mniej konkretny. (Każda podwójnie tablica jest obiekt , jednak nie każdy obiekt jest podwójna tablica ). Od najbardziej konstruktor więc kłopotliwe (dwukrotnie []) , co wyjaśnia wyjście programu.
To zachowanie ma sens, jeśli przekażesz wartość typu double [] ; jeśli przekażesz null, jest sprzeczne z intuicją . Kluczem do zrozumienia tej zagadki jest to, że test, dla której metoda lub konstruktor jest najbardziej specyficzny, nie wykorzystuje rzeczywistych parametrów : parametrów pojawiających się w wywołaniu. Służą one jedynie do określenia, które przeciążenia mają zastosowanie. Gdy kompilator ustali, które przeciążenia mają zastosowanie i są dostępne, wybiera najbardziej specyficzne przeciążenie, używając tylko parametrów formalnych: parametrów pojawiających się w deklaracji.
Aby wywołać konstruktor Confusing (Object) z parametrem null , napisz nowy Confusing ((Object) null) . Gwarantuje to, że ma zastosowanie tylko Confusing (Object) . Mówiąc bardziej ogólnie, aby zmusić kompilator do wybrania określonego przeciążenia, należy rzutować rzeczywiste parametry na zadeklarowane typy parametrów formalnych.