31 Stimmen

Wofür wird Method.isBridge verwendet?

Während der Navigation auf dem java.lang.reflect.Method Klasse bin ich auf die Methode isBridge . Die Javadoc besagt, dass sie nur dann true zurückgibt, wenn die Java-Spezifikation die Methode als true deklariert.

Bitte helfen Sie mir zu verstehen, wofür dies verwendet wird! Kann eine benutzerdefinierte Klasse ihre Methode bei Bedarf als Brücke deklarieren?

30voto

VonC Punkte 1117238

Eine Brückenmethode kann vom Compiler erstellt werden, wenn ein parametrisierter Typ erweitert wird, dessen Methoden parametrisierte Argumente haben.

Sie können in dieser Klasse finden BridgeMethodResolver eine Möglichkeit, die eigentliche Methode zu erhalten, auf die eine "Brückenmethode" verweist.

Ver Rahmen erstellen, synchronisieren, Kontrolle übertragen :

Ein Beispiel für eine solche Situation sind die folgenden Erklärungen:

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

Nun, bei einem Aufruf

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

Die Löschung der tatsächlich aufgerufenen Methode, D.id(String) unterscheidet sich in seiner Signatur von der der Methodendeklaration zur Kompilierzeit, C.id(Object) . Ersterer nimmt ein Argument vom Typ String entgegen, während letzterer ein Argument vom Typ Object entgegennimmt. Der Aufruf schlägt mit einer ClassCastException fehl, bevor der Körper der Methode ausgeführt wird.

Solche Situationen können nur entstehen, wenn das Programm eine ungeprüfte Warnung auslöst ( §5.1.9 ).

Implementierungen können diese Semantik durch die Erstellung von Brückenmethoden erzwingen. Im obigen Beispiel würde die folgende Brückenmethode in der Klasse D erstellt werden:

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

Dies ist die Methode, die tatsächlich von der virtuellen Java-Maschine als Reaktion auf den Aufruf aufgerufen wird c.id(new Object()) wie oben gezeigt, und führt den Cast aus oder scheitert, je nach Bedarf.

Siehe auch Brücke :

wie im Kommentar erwähnt, werden auch Brückenmethoden benötigt für kovariante Übersteuerung :

  • In Java 1.4 und früher kann eine Methode eine andere außer Kraft setzen, wenn die Signaturen genau übereinstimmen.
  • In Java 5 kann eine Methode eine andere außer Kraft setzen, wenn die Argumente genau übereinstimmen aber der Rückgabetyp der überschreibenden Methode, wenn es sich um eine Untertyp des Rückgabetyps der anderen Methode.

Typischerweise wird eine Methode Object clone() kann überschrieben werden durch eine MyObject clone() , aber der Compiler erzeugt eine Brückenmethode:

public bridge Object MyObject.clone();

2 Stimmen

Auch ohne Generika sind Brückenmethoden für kovariante Rückgabetypen notwendig.

0 Stimmen

@BrunoJCM guter Fang. Ich habe den Link wiederhergestellt (die Klasse wurde von Projekt org.springframework.core zum Projekt spring-framework : fisheye.springsource.org/browse/spring-framework/ )

0 Stimmen

Eine dritte Verwendung von Brückenmethoden ist die Änderung der Sichtbarkeit einer Methode auf öffentlich, wenn die Klasse mit der Sichtbarkeit package private deklariert wurde.

3voto

samskivert Punkte 3634

Das dort gezeigte Beispiel (zitiert aus der JLS) lässt es so klingen, als würden Bridge-Methoden nur in Situationen verwendet, in denen rohe Typen verwendet werden. Da dies nicht der Fall ist, möchte ich ein Beispiel anführen, in dem Brückenmethoden für völlig typgerechten generischen Code verwendet werden.

Betrachten Sie die folgende Schnittstelle und Funktion:

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);
}

Wenn Sie diesen Code auf die folgende Weise verwenden, wird eine Brückenmethode verwendet:

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

Nach dem Löschen wird die Function Interface enthält die Methode apply(Object)Object (was Sie durch Dekompilieren des Bytecodes bestätigen können). Natürlich, wenn Sie sich den dekompilierten Code für applyFunc sehen Sie, dass es einen Aufruf an apply(Object)Object . Object ist die obere Grenze seiner Typvariablen, so dass keine andere Signatur sinnvoll wäre.

Wenn also eine anonyme Klasse mit der Methode apply(String)String implementiert es nicht wirklich die Function Schnittstelle, es sei denn, es wird eine Brückenmethode erstellt. Die Bridge-Methode erlaubt es allen generisch typisierten Code, diese Schnittstelle zu nutzen Function Umsetzung.

Interessanterweise nur, wenn die Klasse einige andere Schnittstelle mit der Signatur apply(String)String und nur wenn die Methode über eine Referenz dieses Schnittstellentyps aufgerufen wird, würde der Compiler einen Aufruf mit dieser Signatur ausgeben.

Auch wenn ich den folgenden Code habe:

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

Der Compiler gibt weiterhin einen Aufruf an apply(Object)Object .

Es gibt tatsächlich noch eine andere Möglichkeit, den Compiler dazu zu bringen, Folgendes aufzurufen apply(String)String Sie macht sich jedoch den magischen Typ zunutze, der einem anonymen Klassenerstellungsausdruck zugewiesen ist, der sonst nicht aufgeschrieben werden kann:

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

0voto

Jesse Glick Punkte 23182

Ein weiterer Fall, über den ich gestolpert bin, hat nichts mit Generika zu tun:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X