2008-11-14 5 views
27

Podczas nawigacji klasy Method natknąłem się na funkcję isBridge(), której javadoc mówi, że jest prawdziwa tylko wtedy, gdy specyfikacja java deklaruje, że ta metoda jest prawdziwa.do czego służy java.lang.reflect.Method.isBridge()?

Proszę mi pomóc zrozumieć, do czego jest to używane? Czy klasa niestandardowa może zadeklarować swoją metodę jako most, jeśli jest to wymagane?

Odpowiedz

27

Metoda mostu może zostać utworzona przez kompilator podczas rozszerzania sparametryzowanego typu, którego metody mają sparametryzowane argumenty.

Można znaleźć w tej klasie BridgeMethodResolver sposób na uzyskanie rzeczywistej Metody, do której odnosi się metoda "pomostowa".

Zobacz Create Frame, Synchronize, Transfer Control:

Jako przykład takiej sytuacji, należy rozważyć deklaracje:

class C<T> { abstract T id(T x); } 
class D extends C<String> { String id(String x) { return x; } } 

Teraz, biorąc pod uwagę inwokacja

C c = new D(); 
c.id(new Object()); // fails with a ClassCastException 

wymazywanie rzeczywistej metody są wywoływane , D.id(String) różni się pod względem podpisu od deklaracji metody kompilacji, C.id(Object). Pierwsza przyjmuje argument typu String, podczas gdy druga przyjmuje argument typu Object. Wywołanie kończy się niepowodzeniem z wyjątkiem ClassCastException, zanim zostanie wykonana treść metody.

Takie sytuacje mogą powstać tylko wtedy, gdy program wygeneruje niezaznaczone ostrzeżenie (§5.1.9).

Implementacje mogą egzekwować te semantyki poprzez tworzenie metod mostkowania. W powyższym przykładzie, poniższa metoda most byłby tworzony w klasie D:

Object id(Object x) { return id((String) x); } 

Jest to metoda, która faktycznie być wywołany przez maszynę wirtualną Javy w odpowiedzi na wezwanie c.id(new Object()) przedstawionym powyżej i będzie wykonywał obsada i niepowodzenie, zgodnie z wymaganiami.

Zobacz także Bridge:

jak wspomniano w komentarzu, potrzebne są również metody most dla kowariantna nadrzędnymi:

  • W Javie 1.4, a wcześniej, jedna metoda może zastąpić inny jeśli podpisy dokładnie odpowiadają .
  • W Javie 5, metoda może zastąpić inny jeśli argumenty dopasować dokładnie ale typ zwracany metody nadrzędnego, jeśli jest to podtyp typu powrotnej z drugiej metody.

Zazwyczaj sposób Object clone() może być zastąpiona przez MyObject clone(), lecz metodą mostu zostaną wygenerowane przez kompilator:

public bridge Object MyObject.clone(); 
+2

Nawet bez generycznych metod mostkowania są konieczne do kowariantnych typów zwracania. –

+0

Link BridgeMethodResolver jest zepsuty :( – BrunoJCM

+0

@BrunoJCM dobry haczyk Mam przywrócić link (klasa została przeniesiona z projektu 'org.springframework.core' do projektu' spring-framework': https://fisheye.springsource.org /browse/spring-framework/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java#rdc41daa3db350ef9a4b14ef1d750d79cb22cf431) – VonC

3

Przykład pokazany tam (cyt JLS) sprawia, że ​​dźwięk jak Metody mostów są używane tylko w sytuacjach, w których używane są typy surowe.Ponieważ tak nie jest, pomyślałem, że wpadnę na przykład, gdzie metody mostowe są używane do generycznego kodu całkowicie poprawnego typowo.

Rozważmy następujący interfejs oraz funkcję:

public static interface Function<A,R> { 
    public R apply (A arg); 
} 
public static <A, R> R applyFunc (Function<A,R> func, A arg) { 
    return func.apply(arg); 
} 

Jeśli użyjesz tego kodu w następujący sposób, używany jest metoda most:

Function<String, String> lower = new Function<String, String>() { 
    public String apply (String arg) { 
     return arg.toLowerCase(); 
    } 
}; 
applyFunc(lower, "Hello"); 

Po skasowaniem, interfejs Function zawiera metodę apply(Object)Object (którą można potwierdzić przez dekompilację kodu bajtowego). Naturalnie, jeśli spojrzysz na dekompilowany kod dla applyFunc, zobaczysz, że zawiera on połączenie z apply(Object)Object. Object to górna granica jego zmiennych typu, więc żadna inna sygnatura nie miałaby sensu.

Tak więc, gdy klasa anonimowa jest tworzona za pomocą metody apply(String)String, nie implementuje ona interfejsu Function, chyba że zostanie utworzona metoda mostu. Metoda bridge pozwala wszystkim ogólnie wpisanym kodom korzystać z tej implementacji Function.

Co ciekawe, tylko jeśli klasa wdrożone pewne inne interfejs z podpisem apply(String)String i tylko wtedy, gdy metoda nazwano poprzez odniesienie tego typu interfejsu będzie kompilator zawsze emitują połączenia z tym podpisem.

Nawet jeśli mam następujący kod:

Function<String, String> lower = ...; 
lower.apply("Hello"); 

Kompilator nadal emituje wywołanie apply(Object)Object.

Jest rzeczywiście jeden sposób, aby uzyskać kompilatora, aby zadzwonić apply(String)String, ale korzysta z magicznym typu przypisanego do anonimowej wypowiedzi tworzenia klasy, która nie może inaczej być zapisane:

new Function<String, String>() { 
    public String apply (String arg) { 
     return arg.toLowerCase(); 
    } 
}.apply("Hello"); 
0

Kolejny przypadek I natknięcie się na to nie ma nic wspólnego z generycznymi:

protected abstract class Super { 
    public void m() {} 
} 
public class Sub extends Super {} 
assert Sub.class.getMethod("m").isBridge();