- 浏览: 335512 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
yueshang520:
太厉害了
Spring读取XML配置源码解析 -
levin_china:
jianyan163qq 写道好文章!我现在遇到一个调用的问题 ...
Java中Runtime.exec的一些事 -
wenlongsust:
exec可能存在注入漏洞,如何控制安全问题啊?
Java中Runtime.exec的一些事 -
RainWu:
...
设计模式感触之代理模式应用 -
ch_dj:
面向对象涉及原则:1.开闭原则2.少用继承,多用聚合3.针对 ...
设计模式感触之代理模式应用
Java中的桥方法是合成方法(synthetic methods),合成方法对于实现Java语言特征是必需的。最广为人知的例子就是协变返回类型和泛型中的案例,在泛型中案例基方法的参数被擦除后与实际被调用的方法不同时会使用到桥方法。
首先来看一个例子:
public class BridgeMethodOne { public static class BMOne<T> { public T getT() { return null; } } public static class BMTwo extends BMOne<String> { public String getT() { return null; } } }
事实上这仅仅是一个协变返回类型的例子,在类型擦除之后看起来和下面的片段类似:
public class BridgeMethodOne { public static class BMOne { public Object getT() { return null; } } public static class BMTwo extends BMOne { public String getT() { return null; } } }
然后在编译反编译之后,BMTwo将和下面类似:
public static class learn.generic.BridgeMethodOne$BMTwo extends learn.generic.BridgeMethodOne$BMOne {
.…
// Method descriptor #15 ()Ljava/lang/String;
// Stack: 1, Locals: 1
public java.lang.String getT();
0 aconst_null
1 areturn
// 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
}
在上面可以看见有一个新的合成方法“java.lang.Object getT()”,这是源代码中没有的。这个方法作为一个桥方法,它所做的全部工作就是将调用代理到“java.lang.String getT()”。因为在JVM里,方法的返回类型是方法签名的一部分,而创建桥方法是实现协变返回类型的方式,因此编译器必须这么做。
现在再来看下面这个泛型指定的例子:
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; } } }
在编译之后,BMTwo将被转换成如下:
public static class learn.generic.BridgeMethodTwo$BMTwo extends learn.generic.BridgeMethodTwo$BMOne {
public java.lang.String getT(java.lang.String args);
0 aload_1 [args]
1 areturn
// 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
}
在这里,桥方法重写了基类BMOne,它不仅做了有参数的调用,同时还执行了到“java.lang.String”的类型转换。这意味着在执行下面的代码忽略编译器的“uncheck”警告时,桥方法将抛出ClassCastException异常。
public static void main(String[] args) { BMOne one = new BMTwo(); one.getT(new Object()); }
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
所列的两个例子是桥方法使用中最广为人知的,但除此之外,桥方法至少还有一个用武之地,那就是被用来改变基类方法的可见性。试着查看下面的例子并尝试着猜测编辑器需要在什么地方创建桥方法。
public class BridgeMethodThree { static class ClassA { public void foo() { } } public static class ClassB extends ClassA { } public static class ClassC extends ClassA { public void foo() { } } }
如果查看ClassB编译后的文件,可以发现发现:
public static class learn.generic.BridgeMethodThree$ClassB extends learn.generic.BridgeMethodThree$ClassA {
public BridgeMethodThree$ClassB();
0 aload_0 [this]
1 invokespecial learn.generic.BridgeMethodThree$ClassA() [8]
4 return
public bridge synthetic void foo();
0 aload_0 [this]
1 invokespecial learn.generic.BridgeMethodThree$ClassA.foo() : void [15]
4 return
}
因为ClassA是包级别限制的,不能被包外访问,而ClassB是公共的,而所有继承的方法必须能够被包外所访问,因此编译器需要桥方法。注意,由于ClassC重写了“foo”方法,不再需要桥方法来增加可见性。
也许还有一些其它地方使用了桥方法,但没有关于这些的源信息。同样,也没有桥方法的定义,虽然从上述的例子已经看出来并可以猜到大致代表什么,但JLS里却没有明确的说明。尽管isBridge是java1.5之后反射API了的公共方法,JVM和JLS没有关于其的确切定义和编译器在何时、如何使用桥方法的定义。一般情况下,当一个类实现了一个参数化的接口或是继承了一个参数化的类时,需要引入桥方法。
英文参考:http://happyenjoylife.iteye.com/blog/1153964
发表评论
-
警告:编码 EUC_CN 的不可映射字符
2013-04-01 15:49 3549使用javac编译时显示: 警告:编码 EUC_CN 的不 ... -
异常处理几则(javac异常与get请求中文乱码)
2013-03-31 18:36 11541 仅当显式请求注释处理时才接受类名称错误 好久没用ja ... -
Java内存管理知识(基础篇)
2013-01-20 16:02 1464第一部分 基础知识 1.1 内存模型 1.2 垃圾回 ... -
Java虚拟机之垃圾收集
2013-01-12 15:07 2921垃圾收集虽说不是JVM ... -
maven坐标查询
2012-12-10 23:11 3274使用maven时,一个经常用到的操作就是去 中央仓库查询相关库 ... -
Maven报错“未结束的字符串字面值” “需要为 class、interface 或 enum”等
2012-12-10 17:26 5877eclipse里面编译完全正常,mvn clean in ... -
String, StringBuilder和StringBuffer性能比较的正确写法
2012-11-22 22:54 2103关于String连接性能的分 ... -
No embedded stylesheet instruction for file:奇怪的错误
2012-11-17 08:14 1330908:09:43,395 INFO [main] Ma ... -
Java中Runtime.exec的一些事
2012-09-09 16:32 500050 预备知识 1 不正确的 ... -
代码重构(一)
2012-08-26 10:55 0真实代码 /** 支付状态校验 * ... -
JAVA正则表达式
2012-08-22 23:04 0JAVA中的正则知识 1.2正则表达式入门 一 ... -
JAVA字节码学习一(初识)
2012-08-20 21:42 0public class MyClass { pub ... -
java类库中Arrays的排序算法探析(Object与泛型类型)
2012-03-10 21:16 1621在Arrays中关于基本类型如int,long,fl ... -
java类库中Arrays的排序算法探析(基础类型)
2012-03-06 23:32 2569java.util.Arrays中有非常方便的array转换为 ... -
Java中List与Array的转换
2012-02-28 18:42 1522在编码中,经常会用到两种存储结构之间的转换,而对 ... -
设计模式感触之代理模式-远程代理
2012-01-08 16:33 36491 远程代理的意义 远程代理为一个位于不同的地址空间的 ... -
设计模式感触之代理模式应用
2012-01-03 17:30 4320设计模式感触之代理模式应用 如果说看完设计模式之 ... -
Java泛型学习
2010-11-06 22:19 1073泛型程序设计(Generic Programming)可以使编 ... -
正在学JAVA的请看看:JAVA学习之路
2010-11-05 15:32 1147JAVA是一种平 ... -
JAVA学习路线图
2010-11-05 15:29 1443最近论坛上看到好几个朋友都在问,如何学习 Java的问 ...
相关推荐
主要介绍了详解java 中泛型中的类型擦除和桥方法的相关资料,需要的朋友可以参考下
JDBC-ODBC桥 这种类型的驱动把所有JDBC的调用传递给ODBC,再让后者调用数据库本地驱动代码(也就是数据库厂商提供的数据库操作二进制代码库,例如Oracle中的oci.dll)。 类型2 本地API驱动 这种类型的驱动通过...
Java 8 简明教程 Java 8 Tutorial中文版 “Java并没有没落,人们很快就会发现这一点” 欢迎阅读我编写的Java 8介绍。本教程将带领你一步一步地认识这门语言的新特 性。通过简单明了的代码示例,你将会学习到如何使用...
在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...
9 7在同步方法中使用wait notif 和nodf3 All 方法 9 8挂起 恢复和终止线程 9 9计时器线程Timer 9 10线程联合 9 11守护线程 习题 第10章输入输出流 10 1File类 10 2FileInputStream类 10 3FileOutputStream类 10 4...
在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...
7.9.4 在构造方法中调用构造方法 184 7.10 方法大汇总 185 7.10.1 本例中用到的类 186 7.10.2 使用例程将本章的知识穿起来 189 7.11 小结:多方位理解Java方法 191 7.12 习题 192 第8章 Java中的包(Package)...
7.9.4 在构造方法中调用构造方法 184 7.10 方法大汇总 185 7.10.1 本例中用到的类 186 7.10.2 使用例程将本章的知识穿起来 189 7.11 小结:多方位理解Java方法 191 7.12 习题 192 第8章 Java中的包(Package)...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
案例1 用户登录验证的完整程序 案例2 MD5的Javabean实现 案例3 用公钥计算消息摘要的验证码 案例4-1 Java中的数字证书的生成及维护方法 案例4-2 数字证书的签发(签名) 案例4-3 利用数字证书给...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...
java连接数据库的两种方法详解,有配套实例,讲解清晰,通俗易懂。
子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。...
Java的COM桥 JCom JCom (Java-COM Bridge) 可以让 Java 程序轻松访问 Windows 平台上的 COM 组件。 JARP JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and ...