Każdy respondent dotąd pozytywnie przyczynił, ale postaram się owinąć się różne pomysły w jedną odpowiedź. Kluczem do zrozumienia, co się dzieje, jest to, w jaki sposób kompilator Java i JVM implementują generyczne - to wyjaśnia mostek i dlaczego jest fałszywe w interfejsie.
Podsumowując, choć:
Metoda bardziej ogólny int op(Number)
wymagana jest zgodność podpisu i skonstruować metodą most wdrażania za
Sposób isBridge()
może być tylko prawdziwe dla konkretnych klas, a nie interfaces
Prawdopodobnie nie ma znaczenia, która z dwóch metod zostanie wybrana - będą działać identycznie w środowisku wykonawczym.
Ok, tutaj jest długa odpowiedź:
implementacja Javy z rodzajowych
Kiedy masz rodzajowe klasy lub interfejsu, kompilator tworzy metodę w pliku klasy z każdego typu rodzajowego zastąpiony odpowiednim rodzajem betonu. Na przykład ITest
ma metodę:
int op(T value)
gdzie klasa definiuje T
jako T extends Number
, więc plik klasa ma metodę:
int op(Number);
Kiedy ITest
służy, kompilator tworzy dodatkowe zajęcia dla każdego wpisz ogólną jest rozstrzygnięty na.Na przykład, jeśli istnieje linia kodu:
ITest<Double> t = new ...
Kompilator tworzy klasę z następujących metod:
int op(Number);
int op(Double);
Ale pewnie tylko JVM musi wersję int op(Double)
? Czy kompilator nie upewnia się, że ITest<Double>
odbiera tylko połączenia pod numerem op(Double)
?
Istnieją dwa powody, dlaczego Java potrzebuje metody int op(Number)
:
orientacja obiektu wymaga, aby wszędzie tam, gdzie użycie klasy można zawsze zastąpić ją podklasy (przynajmniej z bezpieczeństwem typu). Jeśli nie istnieje int op(Number)
, klasa nie zapewni pełnej implementacji sygnatury superklasy (lub super-interfejsu).
Java jest dynamicznym językiem z odlewem i odbiciem, dzięki czemu można wywołać metodę z nieprawidłowym typem. W tym momencie Java gwarantuje, że otrzymasz wyjątek od klasy.
W rzeczywistości implementacja powyższego 2. jest osiągnięta przez kompilator wytwarzający "metodę mostu".
Do czego służy metoda pomostowa?
Kiedy ITest<Double>
tworzony jest z ITest<T extends Number>
, kompilator tworzy metodę int op(Number)
, a jego realizacja jest:
public int op(Number n) {
return this.op((Double) n);
}
Ta implementacja ma dwie właściwości:
gdzie n jest Double
, przekazuje połączenie pod numer int op(Double)
i
Gdzie n jest nie a Double
, powoduje to, że ClassCastException
.
Metoda ta jest "pomostem" od rodzaju ogólnego do typu betonu. Z samej swojej natury, tylko konkretne metody mogą być mostami, więc int op(Double)
na pod-interfejsie jest tylko podpisem.
Co z OP?
Na przykład, w kwestii klasa plik sub interfejs ITestDouble
utworzony przez kompilator zarówno metody:
int op(Number);
int op(Double);
int op(Number)
jest potrzebny, aby implementacje ITestDouble
może mieć swój sposób mostek - , ale ta metoda nie jest sama w sobie mostem, ponieważ jest tylko podpisem, a nie implementacją.Prawdopodobnie Sun/Oracle pominęli tutaj pewną sztuczkę i warto byłoby podnieść z nimi błąd.
Jak znaleźć właściwą metodę?
Po pierwsze, ma to znaczenie? Wszystkie implementacje ITestDouble
będą miały automatycznie wstawioną metodę mostu przez kompilator, a metoda mostu wywoła metodę int op(Double)
. Innymi słowy, to naprawdę nie ma znaczenia, która metoda jest wywoływana, po prostu wybierz jedną.
Po drugie, w czasie wykonywania najprawdopodobniej zostanie przekazany instancje, nie interfejsów. Gdy wykonasz numer getMethods()
, będziesz w stanie odróżnić metodę pomostową od rzeczywistej implementacji. Tak powiedział johncarl.
Po trzecie, jeśli musisz rozwiązać ten problem, przesłuchując interfejs, możesz przetestować argumenty dla "najniższego" podtypu. Na przykład, w meta poziomie:
zebrać wszystkie te dwie metody o tej samej nazwie
Collect typ argumentu: Method.getParameterTypes()[0]
Korzystając Class.isAssignableFrom(Class)
. Metoda zwraca wartość true, jeśli argument jest taki sam lub podklasę klasy, w której wywoływana jest metoda.
Użyj metody z argumentem będącym podklasą pod numerem argumentu innej metody.
Widoczne są tylko mosty na klasach bez interfejsów, ponieważ most jest fragmentem kodu, w którym jedna metoda wywołuje inną. –
Rzeczywiście, więc jak rozumiem, że istnieje tylko jedna metoda "op"? – Flavio
Tak, ale nie znam prostego sposobu mówienia, że są one takie same z samych interfejsów. Możesz spojrzeć na ogólne informacje dla ITest i wywnioskować, że metody są takie same, ale to dużo pracy. –