What is a bridge method?
How to create bridge methods?
Why bridge methods have emerged in the history of Java?
What problems they solve?
These problems were from the Java language or related to some limitation of the JVM?
The bridge methods are synthetic, that is, who introduces them is the compiler. They were introduced in Java 5 and their purpose is to make the covariance of generic types work at the JVM level.
For example:
class A<T> {
public int foo(T x) {
return 42;
}
}
class B extends A<String> {
@Override
public int foo(String x) {
return 53;
}
}
Note that the method foo
class B
override the foo
class A
. However, the parameters are different.
In Java, a subclass/subinterface method overrides another when: (a) has the same name and (b) parameters of the same type. With the advent of generic types, knowing when superscript occurs is more difficult than before, and to make matters worse, the JVM does not have generic types at runtime due to the type-Rasure (erasing).
Because of type-Rasure, what the JVM sees in the class A
at runtime that’s it:
public int foo(Object x) {
return 42;
}
The reason is that generic type T
is erased to its base type, ie, Object
. In the case of a generic type <X extends Y>
, due to type Erasure, all references of the generic type X
are seen by the JVM as occurrences of the type Y
.
To resolve this incompatibility between method types at the JVM level at runtime, the solution is for the compiler to create a synthetic method in the class B
thus:
public int foo(Object x) {
return foo((String) x);
}
There are still other complications due to the type of return. Because in the JVM, for there to be superscripted methods, not only the type of parameters has to be equal, but the type of return as well. Again, this is solved with bridge methods introduced by the compiler that do Casts also with the return value. For example:
import java.lang.reflect.Method;
public class Exemplo {
class C<X, Y> {
public X foo1(Y x) {
return null;
}
public int foo2(Y x) {
return 42;
}
public X foo3(int x) {
return null;
}
}
class D extends C<String, Integer> {
@Override
public String foo1(Integer x) {
return "abc";
}
@Override
public int foo2(Integer x) {
return 53;
}
@Override
public String foo3(int x) {
return "xyz";
}
}
public static void main(String[] args) {
System.out.println("Métodos de C:");
for (Method m : C.class.getMethods()) {
if (m.getDeclaringClass() != Object.class) System.out.println(m);
}
System.out.println();
System.out.println("Métodos de D:");
for (Method m : D.class.getMethods()) {
if (m.getDeclaringClass() != Object.class) System.out.println(m);
}
}
}
Watch the exit:
Métodos de C:
public java.lang.Object Exemplo$C.foo1(java.lang.Object)
public int Exemplo$C.foo2(java.lang.Object)
public java.lang.Object Exemplo$C.foo3(int)
Métodos de D:
public java.lang.Object Exemplo$D.foo1(java.lang.Object)
public java.lang.String Exemplo$D.foo1(java.lang.Integer)
public int Exemplo$D.foo2(java.lang.Object)
public int Exemplo$D.foo2(java.lang.Integer)
public java.lang.String Exemplo$D.foo3(int)
public java.lang.Object Exemplo$D.foo3(int)
Notice that in class D
, all three methods foo1
, foo2
and foo3
are duplicated. Duplicates using generic base types (Object
in this case) are bridge methods. Also note that generic types appear for the class C
have been erased to their base types.
Official reference:
- Does this feature have any parallel in any other language? Which language? What problem in that other language is solved with this?
I don’t know, but I can’t say it doesn’t exist. In the case of languages with dynamic typing such as Python, Javascript and largely (but not at all) PHP, bridge methods would have no sense of existence, but in languages with static typing, they might. At bottom, bridge methods are a gambit to solve a JVM limitation, and therefore, it makes little sense that such a thing exists in most other programming languages.
- Other languages that target JVM by default need to be alert to the existence of these methods?
Yes, but in very rare cases. Even in Java, bridge methods rarely cause any problems. This only becomes a problem when you are doing some operation with Reflection and the presence of bridge methods gets in your way, just like you did in your previous question. But that kind of circumstance is something quite unusual.
To help while Victor doesn’t come to answer :) https://stackoverflow.com/q/5007357/221800. It’s not even good there, I think you’ll have a much better answer here. Just re-read the first paragraph :)
– Maniero