看springframework源码中关于ConfigurationClassParser在解析一个配置类的时候需要扫描某一配置类申明的带有@Bean注解所有方法,然后过滤掉bridge method,然后再继续解析。之前在看Java的泛型机制的时候有看到过关于bridge method,下面来介绍下相关概念。
先看下面这段代码:
public class Node<T> {
public T data;
public Node(T data) {
this.data = data;
}
public void setData(T data) {
System.out.println("Node.setData");
this.data = data;
}
}
public class MyNode extends Node<Integer> {
public MyNode(Integer data) {
super(data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
public static void main(String[] args){
MyNode mn = new MyNode(5);
Node n = mn;
n.setData("dddd");
String dd = (String)n.data;
}
}
上面的代码编译不会出现问题,但是当运行时n.setData(“dddd”)这行会报错,为什么呢?熟悉Java泛型的都知道Java里面泛型只是一种语法糖,编译后其实会把泛型给擦除掉,擦除后的代码相当于下面这样:
public class Node {
public Object data;
public Node(Object data) { this.data = data; }
public void setData(Object data) {
System.out.println("Node.setData");
this.data = data;
}
}
public class MyNode extends Node {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
观察发现擦除后的代码会导致MyNode的setData方法没有对Node的setData方法形成覆盖。
为什么需要bridge method
所以对于上面这种情况,为了解决泛型擦除后保留多态的特性,Java编译器会生成synthetic方法也就是bridge method。如下:
class MyNode extends Node {
// Bridge method generated by the compiler
//
public void setData(Object data) {
setData((Integer) data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
// ...
}
针对于上面第一段代码运行时n.setData(“dddd”)报错,大家看了上面的代码后就知道为什么了。
其他生成bridge method的情况
同样,在java中子类Overriding父类方法的时候,由于返回类型可以不保持一模一样,这个时候如果不引入bridge method,则会造成方法的Overriding失效。