电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

詳解Java的橋接方法

瀏覽:14日期:2022-08-19 13:21:23
什么是橋接方法?

Java中的橋接方法(Bridge Method)是一種為了實現(xiàn)某些Java語言特性而由編譯器自動生成的方法。

我們可以通過Method類的isBridge方法來判斷一個方法是否是橋接方法。

在字節(jié)碼文件中,橋接方法會被標(biāo)記為ACC_BRIDGE和ACC_SYNTHETIC,其中ACC_BRIDGE用于表示該方法是由編譯器產(chǎn)生的橋接方法,ACC_SYNTHETIC用于表示該方法是由編譯器自動生成。

什么時候生成橋接方法?

為了實現(xiàn)哪些Java語言特性會生成橋接方法?最常見的兩種情況就是協(xié)變返回值類型和類型擦除,因為它們導(dǎo)致了父類方法的參數(shù)和實際調(diào)用的方法參數(shù)類型不一致。下面我們通過兩個例子更好地理解一下。

協(xié)變返回類型

協(xié)變返回類型是指子類方法的返回值類型不必嚴(yán)格等同于父類中被重寫的方法的返回值類型,而可以是更 '具體' 的類型。

在Java 1.5添加了對協(xié)變返回類型的支持,即子類重寫父類方法時,返回的類型可以是子類方法返回類型的子類。下面看一個例子:

public class Parent { Number get() { return 1; }}

public class Child extends Parent { @Override Integer get() { return 1; }}

Child類重寫其父類Parent的get方法,Parent的get方法返回類型為Number,而Child類中g(shù)et方法返回類型為Integer。

將這段代碼進(jìn)行編譯,再反編譯:

javac Child.javajavap -v -c Child.class

結(jié)果如下:

public class Child extends Parent......省略部分結(jié)果...... java.lang.Integer get(); descriptor: ()Ljava/lang/Integer; flags: Code: stack=1, locals=1, args_size=1 0: iconst_1 1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 4: areturn LineNumberTable: line 5: 0 java.lang.Number get(); descriptor: ()Ljava/lang/Number; flags: ACC_BRIDGE, ACC_SYNTHETIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokevirtual #3 // Method get:()Ljava/lang/Integer; 4: areturn LineNumberTable: line 1: 0

從上面的結(jié)果可以看到,有一個方法java.lang.Number get(), 在源碼中是沒有出現(xiàn)過的,是由編譯器自動生成的,該方法被標(biāo)記為ACC_BRIDGE和ACC_SYNTHETIC,就是我們前面所說的橋接方法。

這個方法就起了一個橋接的作用,它所做的就是把對自身的調(diào)用通過invokevirtual指令再調(diào)用方法java.lang.Integer get()。

編譯器這么做的原因是什么呢?因為在JVM方法中,返回類型也是方法簽名的一部分,而橋接方法的簽名和其父類的方法簽名一致,以此就實現(xiàn)了協(xié)變返回值類型。

類型擦除

泛型是Java 1.5才引進(jìn)的概念,在這之前是沒有泛型的概念的,但泛型代碼能夠很好地和之前版本的代碼很好地兼容,這是為什么呢?

這是因為,在編譯期間Java編譯器會將類型參數(shù)替換為其上界(類型參數(shù)中extends子句的類型),如果上界沒有定義,則默認(rèn)為Object,這就叫做類型擦除。

當(dāng)一個子類在繼承(或?qū)崿F(xiàn))一個父類(或接口)的泛型方法時,在子類中明確指定了泛型類型,那么在編譯時編譯器會自動生成橋接方法,例如:

public class Parent<T> { void set(T t) { }}

public class Child extends Parent<String> { @Override void set(String str) { }}

Child類在繼承其父類Parent的泛型方法時,明確指定了泛型類型為String,將這段代碼進(jìn)行編譯,再反編譯:

public class Child extends Parent<java.lang.String>......省略部分結(jié)果...... void set(java.lang.String); descriptor: (Ljava/lang/String;)V flags: Code: stack=0, locals=2, args_size=2 0: return LineNumberTable: line 5: 0 void set(java.lang.Object); descriptor: (Ljava/lang/Object;)V flags: ACC_BRIDGE, ACC_SYNTHETIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: checkcast #2 // class java/lang/String 5: invokevirtual #3 // Method set:(Ljava/lang/String;)V 8: return LineNumberTable: line 1: 0

從上面的結(jié)果可以看到,有一個方法void set(java.lang.Object), 在源碼中是沒有出現(xiàn)過的,是由編譯器自動生成的,該方法被標(biāo)記為ACC_BRIDGE和ACC_SYNTHETIC,就是我們前面所說的橋接方法。

這個方法就起了一個橋接的作用,它所做的就是把對自身的調(diào)用通過invokevirtual指令再調(diào)用方法void set(java.lang.String)。

編譯器這么做的原因是什么呢?因為Parent類在類型擦除之后,變成這樣:

public class Parent<Object> { void set(Object t) { }}

編譯器為了讓子類有一個與父類的方法簽名一致的方法,就在子類自動生成一個與父類的方法簽名一致的橋接方法。

如何查找橋接方法的實際方法

在Spring Framework中已經(jīng)實現(xiàn)了查找橋接方法的實際方法的功能,就在spring-core模塊中的BridgeMethodResolver類中,像這樣直接使用就行了:

method = BridgeMethodResolver.findBridgedMethod(method);

findBridgedMethod方法是怎么實現(xiàn)的呢?我們來分析一下源碼(spring-core的版本為5.2.8.RELEASE):

public static Method findBridgedMethod(Method bridgeMethod) { // 如果不是橋連方法,就直接返回原方法。if (!bridgeMethod.isBridge()) {return bridgeMethod;} // 先從本地緩存讀取,緩存中有則直接返回。Method bridgedMethod = cache.get(bridgeMethod);if (bridgedMethod == null) {List<Method> candidateMethods = new ArrayList<>(); // 以方法名稱和入?yún)€數(shù)相等為篩選條件。MethodFilter filter = candidateMethod ->isBridgedCandidateFor(candidateMethod, bridgeMethod); // 遞歸該類及其所有父類上的所有方法,符合篩選條件就添加進(jìn)來。ReflectionUtils.doWithMethods(bridgeMethod.getDeclaringClass() , candidateMethods::add, filter);if (!candidateMethods.isEmpty()) { // 如果符合篩選條件的方法個數(shù)為1,則直接采用; // 否則,調(diào)用searchCandidates方法再次篩選。bridgedMethod = candidateMethods.size() == 1 ?candidateMethods.get(0) :searchCandidates(candidateMethods, bridgeMethod);} // 如果找不到實際方法,則返回原來的橋連方法。if (bridgedMethod == null) {// A bridge method was passed in but we couldn’t find the bridged method.// Let’s proceed with the passed-in method and hope for the best...bridgedMethod = bridgeMethod;} // 把查找的結(jié)果放入內(nèi)存緩存。cache.put(bridgeMethod, bridgedMethod);}return bridgedMethod;}

我們再看一下再次篩選的searchCandidates方法是如何實現(xiàn)的:

private static Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod) {if (candidateMethods.isEmpty()) {return null;}Method previousMethod = null;boolean sameSig = true; // 遍歷候選方法的列表for (Method candidateMethod : candidateMethods) { // 對比橋接方法的泛型類型參數(shù)和候選方法是否匹配,如果匹配則直接返回該候選方法。if (isBridgeMethodFor(bridgeMethod, candidateMethod, bridgeMethod.getDeclaringClass())) {return candidateMethod;}else if (previousMethod != null) { // 如果不匹配,則判斷所有候選方法的參數(shù)列表是否相等。sameSig = sameSig && Arrays.equals(candidateMethod.getGenericParameterTypes(), previousMethod.getGenericParameterTypes());}previousMethod = candidateMethod;} // 如果所有候選方法的參數(shù)列表全相等,則返回第一個候選方法。return (sameSig ? candidateMethods.get(0) : null);}

總結(jié)以上源碼就是,通過判斷方法名、參數(shù)的個數(shù)以及泛型類型參數(shù)來獲取橋接方法的實際方法。

以上就是詳解Java的橋接方法的詳細(xì)內(nèi)容,更多關(guān)于java 橋接方法的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 泰安塞纳春天装饰公司【网站】| 济南画室培训-美术高考培训-山东艺霖艺术培训画室 | 润滑油加盟_润滑油厂家_润滑油品牌-深圳市沃丹润滑科技有限公司 琉璃瓦-琉璃瓦厂家-安徽盛阳新型建材科技有限公司 | 网站建设,北京网站建设,北京网站建设公司,网站系统开发,北京网站制作公司,响应式网站,做网站公司,海淀做网站,朝阳做网站,昌平做网站,建站公司 | 减速机电机一体机_带电机减速器一套_德国BOSERL电动机与减速箱生产厂家 | 深圳高新投三江工业消防解决方案提供厂家_服务商_园区智慧消防_储能消防解决方案服务商_高新投三江 | 电梯装饰-北京万达中意电梯装饰有限公司 | 贴片电容-贴片电阻-二三极管-国巨|三星|风华贴片电容代理商-深圳伟哲电子 | 杜康白酒加盟_杜康酒代理_杜康酒招商加盟官网_杜康酒厂加盟总代理—杜康酒神全国运营中心 | 泰国试管婴儿_泰国第三代试管婴儿费用|成功率|医院—新生代海外医疗 | 纯水设备_苏州皙全超纯水设备水处理设备生产厂家 | 沧州友城管业有限公司-内外涂塑钢管-大口径螺旋钢管-涂塑螺旋管-保温钢管生产厂家 | 高温高压釜(氢化反应釜)百科 | 模温机-油温机-电加热导热油炉-工业冷水机「欧诺智能」 | 中央空调维修、中央空调保养、螺杆压缩机维修-苏州东菱空调 | 亿诺千企网-企业核心产品贸易 | 浙江红酒库-冰雕库-气调库-茶叶库安装-医药疫苗冷库-食品物流恒温恒湿车间-杭州领顺实业有限公司 | 品牌广告服务平台,好排名,好流量,好生意。 | 实战IT培训机构_IT培训班选大学生IT技术培训中心_中公优就业 | 断桥铝破碎机_铝合金破碎机_废铁金属破碎机-河南鑫世昌机械制造有限公司 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 美的商用净水器_美的直饮机_一级代理经销商_Midea租赁价格-厂家反渗透滤芯-直饮水批发品牌售后 | 披萨石_披萨盘_电器家电隔热绵加工定制_佛山市南海区西樵南方综合保温材料厂 | 专业生物有机肥造粒机,粉状有机肥生产线,槽式翻堆机厂家-郑州华之强重工科技有限公司 | PTFE接头|聚四氟乙烯螺丝|阀门|薄膜|消解罐|聚四氟乙烯球-嘉兴市方圆氟塑制品有限公司 | 真空乳化机-灌装封尾机-首页-温州精灌 | 耐磨陶瓷管道_除渣器厂家-淄博浩瀚陶瓷科技有限公司 | 喷涂流水线,涂装流水线,喷漆流水线-山东天意设备科技有限公司 | 金属波纹补偿器厂家_不锈钢膨胀节价格_非金属伸缩节定制-庆达补偿器 | 馋嘴餐饮网_餐饮加盟店火爆好项目_餐饮连锁品牌加盟指南创业平台 | 三轴曲线机-端子插拔力试验机|华杰仪器| 回转支承-转盘轴承-回转驱动生产厂家-洛阳隆达轴承有限公司 | 有源电力滤波装置-电力有源滤波器-低压穿排电流互感器|安科瑞 | 真空乳化机-灌装封尾机-首页-温州精灌 | 步进电机_agv电机_伺服马达-伺服轮毂电机-和利时电机 | 户外环保不锈钢垃圾桶_标识标牌制作_园林公园椅厂家_花箱定制-北京汇众环艺 | 英超直播_英超免费在线高清直播_英超视频在线观看无插件-24直播网 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 防水试验机_防水测试设备_防水试验装置_淋雨试验箱-广州岳信试验设备有限公司 | 合肥抖音SEO网站优化-网站建设-网络推广营销公司-百度爱采购-安徽企匠科技 | 车牌识别道闸_停车场收费系统_人脸识别考勤机_速通门闸机_充电桩厂家_中全清茂官网 |