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

您的位置:首頁技術文章
文章詳情頁

詳解Java的橋接方法

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

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

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

在字節碼文件中,橋接方法會被標記為ACC_BRIDGE和ACC_SYNTHETIC,其中ACC_BRIDGE用于表示該方法是由編譯器產生的橋接方法,ACC_SYNTHETIC用于表示該方法是由編譯器自動生成。

什么時候生成橋接方法?

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

協變返回類型

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

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

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

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

Child類重寫其父類Parent的get方法,Parent的get方法返回類型為Number,而Child類中get方法返回類型為Integer。

將這段代碼進行編譯,再反編譯:

javac Child.javajavap -v -c Child.class

結果如下:

public class Child extends Parent......省略部分結果...... 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

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

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

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

類型擦除

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

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

當一個子類在繼承(或實現)一個父類(或接口)的泛型方法時,在子類中明確指定了泛型類型,那么在編譯時編譯器會自動生成橋接方法,例如:

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

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

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

public class Child extends Parent<java.lang.String>......省略部分結果...... 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

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

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

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

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

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

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

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

method = BridgeMethodResolver.findBridgedMethod(method);

findBridgedMethod方法是怎么實現的呢?我們來分析一下源碼(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<>(); // 以方法名稱和入參個數相等為篩選條件。MethodFilter filter = candidateMethod ->isBridgedCandidateFor(candidateMethod, bridgeMethod); // 遞歸該類及其所有父類上的所有方法,符合篩選條件就添加進來。ReflectionUtils.doWithMethods(bridgeMethod.getDeclaringClass() , candidateMethods::add, filter);if (!candidateMethods.isEmpty()) { // 如果符合篩選條件的方法個數為1,則直接采用; // 否則,調用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;} // 把查找的結果放入內存緩存。cache.put(bridgeMethod, bridgedMethod);}return bridgedMethod;}

我們再看一下再次篩選的searchCandidates方法是如何實現的:

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

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

以上就是詳解Java的橋接方法的詳細內容,更多關于java 橋接方法的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 搅拌磨|搅拌球磨机|循环磨|循环球磨机-无锡市少宏粉体科技有限公司 | 精雕机-火花机-精雕机 cnc-高速精雕机-电火花机-广东鼎拓机械科技有限公司 | 电子元器件呆滞料_元器件临期库存清仓尾料_尾料优选现货采购处理交易商城 | 水环真空泵厂家,2bv真空泵,2be真空泵-淄博真空设备厂 | 全自动端子机|刺破式端子压接机|全自动双头沾锡机|全自动插胶壳端子机-东莞市傅氏兄弟机械设备有限公司 | 对夹式止回阀厂家,温州对夹式止回阀制造商--永嘉县润丰阀门有限公司 | 匀胶机旋涂仪-声扫显微镜-工业水浸超声-安赛斯(北京)科技有限公司 | 电脑刺绣_绣花厂家_绣花章仔_织唛厂家-[源欣刺绣]潮牌刺绣打版定制绣花加工厂家 | 聚天冬氨酸,亚氨基二琥珀酸四钠,PASP,IDS - 远联化工 | 常州翔天实验仪器厂-恒温振荡器-台式恒温振荡器-微量血液离心机 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 「银杏树」银杏树行情价格_银杏树种植_山东程锦园林 | 废气处理_废气处理设备_工业废气处理_江苏龙泰环保设备制造有限公司 | LED投光灯-工矿灯-led路灯头-工业灯具 - 山东普瑞斯照明科技有限公司 | 定制奶茶纸杯_定制豆浆杯_广东纸杯厂_[绿保佳]一家专业生产纸杯碗的厂家 | 电动垃圾车,垃圾清运车-江苏速利达机车有限公司 | 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 广州/东莞小字符喷码机-热转印打码机-喷码机厂家-广州瑞润科技 | 齿轮减速机_齿轮减速电机-VEMT蜗轮蜗杆减速机马达生产厂家瓦玛特传动瑞环机电 | 噪声治理公司-噪音治理专业隔音降噪公司 | 高精度-恒温冷水机-螺杆式冰水机-蒸发冷冷水机-北京蓝海神骏科技有限公司 | 蜜蜂职场文库_职场求职面试实用的范文资料大全| 渗透仪-直剪仪-三轴仪|苏州昱创百科 | 江西高职单独招生-江西单招考试-江西高职单招网 | 科普仪器菏泽市教育教学仪器总厂 | 耐腐蚀泵,耐腐蚀真空泵,玻璃钢真空泵-淄博华舜耐腐蚀真空泵有限公司 | 酒精检测棒,数显温湿度计,酒安酒精测试仪,酒精检测仪,呼气式酒精检测仪-郑州欧诺仪器有限公司 | 环氧树脂地坪漆_济宁市新天地漆业有限公司 | 石家庄律师_石家庄刑事辩护律师_石家庄取保候审-河北万垚律师事务所 | 衬塑设备,衬四氟设备,衬氟设备-淄博鲲鹏防腐设备有限公司 | 塑胶跑道_学校塑胶跑道_塑胶球场_运动场材料厂家_中国塑胶跑道十大生产厂家_混合型塑胶跑道_透气型塑胶跑道-广东绿晨体育设施有限公司 | 牛奶检测仪-乳成分分析仪-北京海谊| 岩石钻裂机-液压凿岩机-劈裂机-挖改钻_湖南烈岩科技有限公司 | 板框压滤机-隔膜压滤机-厢式压滤机生产厂家-禹州市君工机械设备有限公司 | 震动筛选机|震动分筛机|筛粉机|振筛机|振荡筛-振动筛分设备专业生产厂家高服机械 | 5L旋转蒸发器-20L-50L旋转蒸发器-上海越众仪器设备有限公司 | 加气混凝土砌块设备,轻质砖设备,蒸养砖设备,新型墙体设备-河南省杜甫机械制造有限公司 | IP检测-检测您的IP质量| 动物麻醉机-数显脑立体定位仪-北京易则佳科技有限公司 | 郑州外墙清洗_郑州玻璃幕墙清洗_郑州开荒保洁-河南三恒清洗服务有限公司 | 欧盟ce检测认证_reach检测报告_第三方检测中心-深圳市威腾检验技术有限公司 | 澳威全屋定制官网|极简衣柜十大品牌|衣柜加盟代理|全屋定制招商 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 |