Bridge Methods in Java
When you write class Marks implements Comparable<Marks> with a compareTo(Marks other) method, you're overriding Comparable's compareTo(T other). But after type erasure, Comparable really declares compareTo(Object other). Your method's parameter is Marks, not Object, so to the JVM it doesn't override anything. The compiler quietly fixes this by adding a bridge method: a hidden compareTo(Object) that casts and calls yours.
Seeing the Bridge
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class Ranking {
static class Marks implements Comparable<Marks> {
final String name;
final int value;
Marks(String name, int value) {
this.name = name;
this.value = value;
}
@Override
public int compareTo(Marks other) {
return Integer.compare(value, other.value);
}
}
public static void main(String[] args) {
for (Method m : Marks.class.getDeclaredMethods()) {
if (m.getName().equals("compareTo")) {
System.out.println(Arrays.toString(m.getParameterTypes())
+ " bridge=" + m.isBridge());
}
}
List<Marks> list = Arrays.asList(new Marks("Navika", 91),
new Marks("Srihitha", 88), new Marks("Advitha", 95));
list.sort(null);
System.out.println(list.get(0).name + " is lowest");
}
}[class Ranking$Marks] bridge=false
[class java.lang.Object] bridge=true
Srihitha is lowestHow it works
- The class has two
compareTomethods: yours, takingMarks, and a bridge takingObject, which the reflection API reports withisBridge() = true. (Their order in the list can vary.) - Sorting code calls
compareTo(Object)through the erasedComparableinterface. That reaches the bridge, which casts the argument toMarksand calls your method.
javap shows what the bridge does:
public int compareTo(Bridge$Marks);
public int compareTo(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: checkcast #8 // class Bridge$Marks
5: invokevirtual #19 // Method compareTo:(LBridge$Marks;)I
8: ireturnWhen Bridges Appear
| Situation | Bridge generated |
|---|---|
Implementing a generic interface with a concrete type: Comparable<Marks> | compareTo(Object) |
| Extending a generic class and overriding with a concrete type | A method with the parent's erased signature |
| A covariant return type (see "Covariant Return Type in Java") | A method with the parent's return type |
You never write or call bridge methods yourself. You'll notice them only in javap output, in stack traces (where they can appear as an extra line at the same source line), and when using reflection, where isBridge() lets frameworks skip them.
Common Mistakes
Being confused by two compareTo methods in reflection output. One is the bridge; check isBridge().
Trying to write compareTo(Object) yourself as well. It clashes with the bridge's signature.
Thinking bridges slow programs down. The JIT inlines them; the cost is negligible.
Practice
- Easy: Run
javap -pon a class implementingComparator<String>and find the bridge forcompare. - Harder: Write
class Box<T> { T get() { return null; } }andclass NameBox extends Box<String> { @Override String get() { return "Navika"; } }. Use reflection to listNameBox'sgetmethods and mark which is the bridge.
Key Takeaways
Was this tutorial helpful?