Java Generics-metoda brydżowa?
Coś, co nazywa się "metodą mostkową", związane z generykami Javy, skłoniło mnie do zatrzymania się i przemyślenia tego.
Btw, wiem tylko, że występuje w bytecode level and is not available do wykorzystania.
Ale chętnie poznam koncepcję "metody mostowej" używanej przez kompilator Javy.
Co dokładnie dzieje się za kulisami i dlaczego jest używany?
Każda pomoc z przykładem będzie bardzo mile widziana.
3 answers
Jest to metoda, która pozwala klasie rozszerzającej klasę generyczną lub implementującej interfejs generyczny (z konkretnym parametrem typu) nadal być używana jako typ surowy.
Wyobraź sobie to:
public class MyComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
//
}
}
To nie może być użyte w jego surowej formie, przechodząc dwa Object
s do porównania, ponieważ typy są kompilowane w metodzie compare(w przeciwieństwie do tego, co by się stało, gdyby był to ogólny parametr typu T, gdzie Typ zostanie usunięty). Więc zamiast tego, za kulisami, kompilator dodaje " most metoda", która wygląda mniej więcej tak (gdyby to było źródło Javy):
public class MyComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
//
}
//THIS is a "bridge method"
public int compare(Object a, Object b) {
return compare((Integer)a, (Integer)b);
}
}
Kompilator chroni dostęp do metody bridge, wymuszając, że jawne wywołania bezpośrednio do niej powodują błąd w czasie kompilacji. Teraz klasa może być również używana w postaci surowej:
Object a = 5;
Object b = 6;
Comparator rawComp = new MyComparator();
int comp = rawComp.compare(a, b);
Dlaczego jeszcze jest to potrzebne?
Oprócz dodawania wsparcia dla jawnego użycia typów surowych (co jest głównie dla wstecznej kompatybilności), metody bridge są również wymagane do obsługi kasowania typów. Z typem kasowanie, metoda taka jak ta:
public <T> T max(List<T> list, Comparator<T> comp) {
T biggestSoFar = list.get(0);
for ( T t : list ) {
if (comp.compare(t, biggestSoFar) > 0) {
biggestSoFar = t;
}
}
return biggestSoFar;
}
Jest w rzeczywistości skompilowany do kodu bajtowego zgodnego z tym:
public Object max(List list, Comparator comp) {
Object biggestSoFar = list.get(0);
for ( Object t : list ) {
if (comp.compare(t, biggestSoFar) > 0) { //IMPORTANT
biggestSoFar = t;
}
}
return biggestSoFar;
}
Jeśli metoda bridge nie istnieje i przekazałeś List<Integer>
i MyComparator
do tej funkcji, wywołanie linii oznaczonej IMPORTANT
zakończy się niepowodzeniem, ponieważ MyComparator
nie ma metody o nazwie compare
, która zajmuje dwa Object
s...tylko jeden, który zajmuje dwa Integer
s.
Poniżej FAQ jest dobrą lekturą.
Zobacz Też:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:31
Warto zauważyć, że kompilator wnioskuje , że MyComparator
'S metoda:
public int compare(Integer a, Integer b) {/* code */}
Próbuje nadpisać Comparator<T>
's
public int compare(T a, T b);
Z deklarowanego typu Comparator<Integer>
. W przeciwnym razie, MyComparator
's compare
będzie traktowana przez kompilator jako dodatkowa (przeciążająca), a nie nadpisująca metoda. I jako taki nie stworzyłby dla niego żadnej metody pomostowej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-02 22:45:08
Jeśli chcesz zrozumieć, dlaczego potrzebujesz metody bridge, lepiej zrozumieć, co się bez niej dzieje. Załóżmy, że nie ma metody bridge.
class A<T>{
private T value;
public void set(T newVal){
value=newVal
}
}
class B extends A<String>{
public void set(String newVal){
System.out.println(newVal);
super.set(newVal);
}
}
Zauważ, że po usunięciu, Metoda set
W A stała się public void set(Object newVal)
, ponieważ nie jest związana z parametrem typu T. nie ma metody w klasie B, której podpis jest taki sam jak set
W A. więc nie ma nadpisywania. Stąd, gdy coś takiego się stało:
A a=new B();
a.set("Hello World!");
Polimorfizm tu nie zadziała. Pamiętaj, że musisz obejść metoda klasy rodzica w klasie potomnej, dzięki której można użyć klasy rodzica var do wywołania polimorfizmu.
To, co robi metoda bridge, polega na cichym nadpisywaniu metody w klasie nadrzędnej wszystkimi informacjami z metody o tej samej nazwie, ale innej sygnaturze. Przy pomocy metody mostkowej zadziałał polimorfizm. Chociaż na powierzchni, nadpisujesz metodę klasy nadrzędnej metodą o innej sygnaturze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 09:59:30