Java中桥方法的作用和真实面目
2016-05-31 07:07
393 查看
在Java的早期版本中,不支持返回类型协变(一个类如果继承/实现了父类/接口的某一个方法,那么返回类型必须与父类/接口的相同),而在Java的后期版本中(具体从几点几开始支持就不太清楚了...)开始支持返回类型协变,支持类型协变的就是Java的桥方法。 接下来列举三个场景来说明桥方法的真实面目和所起到的作用。
场景一:基本的返回类型协变问题
父类代码:
class Father{ public Number test1(){ return null; } }
子类代码:
class Son extends Father{ public Integer test1(){ return null; } /** * // Method descriptor #16 ()Ljava/lang/Number; // Stack: 1, Locals: 1 public bridge synthetic java.lang.Number test1(); 0 aload_0 [this] 1 invokevirtual com.cjs.gohead.generic.classorinterface.Son.test1() : java.lang.Integer [17] 4 areturn */ }
子类中注释的那段即是Java编译器自动生成的桥方法,它由编译器自动生成,存在于class文件,通过那段字节码可以很清楚的看出桥方法的生成。 同时呢返回类型协变也包括泛型擦除(涉及到泛型的实现原理)所引起的一个问题:当一个“子泛型类”实现/继承自一个“父泛型类”的时候,“父泛型类”的类型信息会被擦除为限定类型,这个时候“子泛型类”里面会生成一个桥方法(场景二)。
场景二的例子(注释为编译器所生成的桥方法):
public class BridgeMethodOne { public static class BMOne<T> { // 由于擦除,类型参数T会被替换为限定类型:Object,擦除之 // 后,就与场景一的场景相同了 public T getT() { return null; } } public static class BMTwo extends BMOne<String> { /** // Method descriptor #16()Ljava/lang/Object; // Stack: 1, Locals: 1 public bridge synthetic java.lang.Object getT(); 0 aload_0 [this] 1 invokevirtual learn.generic.BridgeMethodOne$BMTwo.getT() : java.lang.String [17] 4 areturn */ public String getT() { return null; } } }
桥方法还可以解决另一个也是由泛型擦除所引起的问题:当使用泛型类或泛型接口的时候,当被继承/实现的方法(父类中的方法)含有方法参数的时候(并且方法参数为类型参数),由于擦除,会导致子类不会继承/实现父类的方法,所以这个时候就编译器会生成一个方法来解决这个“继承错误”的问题-方法签名不一致(场景三)。
第三个场景的例子(注释为编译器所生成的桥方法):
public class BridgeMethodTwo { public static class BMOne<T> { public T getT(T args) { return args; } } public static class BMTwo extends BMOne<String> { public String getT(String args) { return args; } /** // Method descriptor #18 (Ljava/lang/Object;)Ljava/lang/Object; // Stack: 2, Locals: 2 public bridge synthetic java.lang.Object getT(java.lang.Object arg0); 0 aload_0 [this] 1 aload_1 [arg0] 2 checkcast java.lang.String [19] 5 invokevirtual learn.generic.BridgeMethodTwo$BMTwo.getT(java.lang.String) : java.lang.String [21] 8 areturn */ } }
最后总结一下,Java中的桥方法可以解决返回类型协变的问题(场景一和场景二)和由泛型擦除所引起的看似“继承错误”的问题(场景三)。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序