问题
java为什么会在泛型类的子类生成桥接方法
分析
存在两个类,泛型类A,泛型类A的子类B
泛型类A
/**
* @author xunxing
*/
public class A<T> {
public Integer test(T val) {
System.out.println(val);
return 0;
}
}
泛型类B
/**
* @author xunxing
*/
public class B extends A<String> {
@Override
public Integer test(String val) {
System.out.println("test val");
return 1;
}
public static void main(String[] args) {
A<String> a = new B();
a.test("2");
}
}
在java里,编译器不认识泛型,在java代码编译的时候,会进行类型擦除,我们通过反编译看下类型擦除
泛型类A的反编译
可以看出A的test方法,出参是java/lang/Integer,入参是java/lang/Object,对入参泛型T进行擦除变成Object
泛型类B的反编译
原因
泛型类存在类型擦除的情况,导致A类实际上仅有test(Object)方法,B类只有test(String)方法实际上并没有重写A类的test(Object)方法,很显然这并不是重写,重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变,类型擦除和重写产生的冲突。
java语言的开发者们想到的办法是通过在 B 类中合成一个桥方法来解决这个冲突,桥接方法是对A类 test(Object)方法的覆写,并且函数体调用的是B类的 test(String) 方法,通过B生成桥接方法的反编译可以看出
泛型经过类型擦除会多出桥接方法的坑
**原因:**子类没有指定Integer泛型参数,父类的泛型方法setData(T data)在泛型擦除后是setData(Object data),子类中入参是Integer的setData方法被当作了新方法。因为子类的setData方法没有增加@Override注解,因此编译器没能检测到重写失败的问题
**解决:**方法重写一定要标记@Override注解,可以直接在编译的时候检查出
例子: