bridge method may be created by the compiler when extending a parameterized type whose methods have parameterized arguments.
You can find in this class BridgeMethodResolver a way to get the actual Method referred by a 'bridge method'.
See Create Frame, Synchronize, Transfer Control :
As an example of such a situation, consider the declarations:
class C<T> { abstract T id(T x); } class D extends C<String> { String id(String x) { return x; } }
Now, given an invocation
C c = new D(); c.id(new Object()); // fails with a ClassCastException
The erasure of the actual method being invoked, D.id(String) differs in its signature from that of the compile-time method declaration, C.id(Object) . The former takes an argument of type String while the latter takes an argument of type Object. The invocation fails with a ClassCastException before the body of the method is executed.
Such situations can only arise if the program gives rise to an unchecked warning (§5.1.9 ).
Implementations can enforce these semantics by creating bridge methods. In the above example, the following bridge method would be created in class D:
Object id(Object x) { return id( (String) x ); }
This is the method that would actually be invoked by the Java virtual machine in response to the call c.id(new Object()) shown above, and it will execute the cast and fail, as required.
See also Bridge:
as mentioned in the comment, bridge methods are also needed for covariant overriding:
Typically, a method Object clone() can be overridden by a MyObject clone() , but a bridge method will be generated by the compiler:
public bridge Object MyObject.clone();
=========================================================
The example shown there (quoted from the JLS) makes it sound like bridge methods are only used in situations where raw types are used. Since this is not the case, I thought I'd pipe in with an example where bridge methods are used for totally type-correct generic code.
Consider the following interface and function:
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); }
If you use this code in the following way, a bridge method is used:
Function<String, String> lower = new Function<String, String>() { public String apply (String arg) { return arg.toLowerCase(); } }; applyFunc(lower, "Hello");
After erasure, the Function interface contains the method apply(Object)Object (which you can confirm by decompiling the bytecode). Naturally, if you look at the decompiled code for applyFunc you'll see that it contains a call to apply(Object)Object . Object is the upper bound of its type variables, so no other signature would make sense.
So when an anonymous class is created with the method apply(String)String , it doesn't actually implement the Function interface unless a bridge method is created. The bridge method allows all generically typed code to make use of that Function implementation.
Interestingly, only if the class implemented some other interface with the signature apply(String) String and only if the method was called via a reference of that interface type would the compiler ever emit a call with that signature.
Even if I have the following code:
Function<String, String> lower = ...; lower.apply("Hello");
The compiler still emits a call to apply(Object)Object .
There is actually one other way to get the compiler to call apply(String)String , but it takes advantage of the magical type assigned to an anonymous class creation expression which cannot otherwise be written down:
new Function<String, String>() { public String apply (String arg) { return arg.toLowerCase(); } }.apply("Hello");
=================================================
======
通过下面的例子可以很清楚看到编译器给我们插入了一些方法的实现
import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.springframework.util.ReflectionUtils; /** * 用于测试桥接方法 * @author wenzhihong * */ interface Enable<T> { void say(T t); T getInfo(); } //产生桥接方法 class MyEnable implements Enable<String> { @Override public String getInfo() { return null; } @Override public void say(String t) { } } //不产生桥接方法 class Other<T> implements Enable<T>{ @Override public T getInfo() { return null; } @Override public void say(T t) { } } class MethodInfo{ Class classInfo; String name; Class[] paraTypes; Class returnType; boolean bridge; @Override public String toString() { StringBuilder info = new StringBuilder(); info.append(returnType.getSimpleName() + " " + classInfo.getName() + "." + name + "("); for(Class para : paraTypes){ info.append(para.getSimpleName() + ","); } if(paraTypes.length > 0){ info.setCharAt(info.length()-1, ')'); }else{ info.append(')'); } info.append(" bridge[" + bridge + "]"); return info.toString(); } } public class Test { public static void main(String[] args) { System.out.println("==============产生桥接方法============"); print(MyEnable.class); System.out.println("==============不产生桥接方法================"); print(new Other<String>().getClass()); } private static void print(Class cls) { final List<MethodInfo> result = new ArrayList<MethodInfo>(); ReflectionUtils.doWithMethods(cls, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { MethodInfo info = new MethodInfo(); info.classInfo = method.getDeclaringClass(); info.name = method.getName(); info.paraTypes = method.getParameterTypes(); info.returnType = method.getReturnType(); info.bridge = method.isBridge(); result.add(info); } }); for(MethodInfo info : result){ System.out.println(info); } } }
执行输出
==============产生桥接方法============ void MyEnable.say(String) bridge[false] void MyEnable.say(Object) bridge[true] String MyEnable.getInfo() bridge[false] Object MyEnable.getInfo() bridge[true] void java.lang.Object.finalize() bridge[false] void java.lang.Object.wait() bridge[false] void java.lang.Object.wait(long,int) bridge[false] void java.lang.Object.wait(long) bridge[false] int java.lang.Object.hashCode() bridge[false] Class java.lang.Object.getClass() bridge[false] Object java.lang.Object.clone() bridge[false] boolean java.lang.Object.equals(Object) bridge[false] void java.lang.Object.registerNatives() bridge[false] String java.lang.Object.toString() bridge[false] void java.lang.Object.notify() bridge[false] void java.lang.Object.notifyAll() bridge[false] ==============不产生桥接方法================ void Other.say(Object) bridge[false] Object Other.getInfo() bridge[false] void java.lang.Object.finalize() bridge[false] void java.lang.Object.wait() bridge[false] void java.lang.Object.wait(long,int) bridge[false] void java.lang.Object.wait(long) bridge[false] int java.lang.Object.hashCode() bridge[false] Class java.lang.Object.getClass() bridge[false] Object java.lang.Object.clone() bridge[false] boolean java.lang.Object.equals(Object) bridge[false] void java.lang.Object.registerNatives() bridge[false] String java.lang.Object.toString() bridge[false] void java.lang.Object.notify() bridge[false] void java.lang.Object.notifyAll() bridge[false]
认真比较输出信息, 相信大家可以很容易理解什么是桥接方法.
桥接方法也就是编译器给我们加入了, 为了使java的范型字节码和1.5版本前的字节码相兼容.