成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

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

詳解Java的橋接方法

瀏覽:2日期: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。

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

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才引進的概念,在這之前是沒有泛型的概念的,但泛型代碼能夠很好地和之前版本的代碼很好地兼容,這是為什么呢?

這是因為,在編譯期間Java編譯器會將類型參數(shù)替換為其上界(類型參數(shù)中extends子句的類型),如果上界沒有定義,則默認為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,將這段代碼進行編譯,再反編譯:

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); // 遞歸該類及其所有父類上的所有方法,符合篩選條件就添加進來。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的橋接方法的詳細內(nèi)容,更多關(guān)于java 橋接方法的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
91精品国产综合久久香蕉的特点 | 亚洲成人免费在线| 99久久精品费精品国产一区二区| 欧美高清视频不卡网| 日本不卡的三区四区五区| 国产精品乱看| 一区二区三区四区高清精品免费观看| 一区视频在线看| 国产精品伦一区| 色综合婷婷久久| 日本一区二区三区在线观看| 99视频一区二区三区| 精品国产凹凸成av人导航| 懂色av噜噜一区二区三区av| 欧美精品在线视频| 日本女优在线视频一区二区| 色诱视频网站一区| 免费观看日韩电影| 日本电影欧美片| 蜜臀av国产精品久久久久| 在线亚洲免费视频| 日韩黄色片在线观看| 久久久久久久波多野高潮日日| 亚洲国产综合在线| 久久精品亚洲| 日韩**一区毛片| 欧美自拍丝袜亚洲| 激情小说亚洲一区| 日韩午夜激情视频| 国产91色综合久久免费分享| 日韩视频一区在线观看| 成人的网站免费观看| 精品国产伦一区二区三区观看方式 | 亚洲人123区| 国内激情久久| 亚洲色图一区二区三区| 亚洲精品一区二区三区蜜桃久| 亚洲精品老司机| 午夜在线视频观看日韩17c| 天堂在线一区二区| 在线看不卡av| 国产一区美女在线| 日韩欧美中文字幕一区| 99久久99久久精品免费观看| 久久久99久久精品欧美| 91蝌蚪porny| 国产精品看片你懂得| 一区二区三区福利| 婷婷中文字幕综合| 欧美日韩一区二区三区免费看| 久久精品国产99久久6| 欧美日韩国产一级片| 国产91精品入口| 久久这里只有精品视频网| 欧美呦呦网站| 成人免费一区二区三区在线观看| 国产嫩草一区二区三区在线观看 | 成人午夜视频福利| 国产日韩高清在线| 99国产成+人+综合+亚洲欧美| 亚洲超碰97人人做人人爱| 欧美午夜影院一区| 97se狠狠狠综合亚洲狠狠| 国产精品伦一区| 香蕉久久夜色精品| 国模少妇一区二区三区| 精品对白一区国产伦| 国内精品美女在线观看| 亚洲福利国产精品| 91精品蜜臀在线一区尤物| 97超碰欧美中文字幕| 亚洲精品网站在线观看| 在线观看视频一区二区 | 不卡av在线免费观看| 最新欧美精品一区二区三区| 久久综合狠狠综合久久综青草| 国产在线国偷精品免费看| 久久久久久久久岛国免费| 在线成人亚洲| 麻豆91在线看| 久久综合久久综合久久综合| 亚洲经典在线| 免费成人美女在线观看.| 精品欧美久久久| 国产精品亚洲产品| 国产精品99久久久久久宅男| 国产精品国产自产拍高清av| 色中色一区二区| 91在线精品一区二区三区| 亚洲精选一二三| 欧美精品乱码久久久久久按摩| 91丨porny丨蝌蚪视频| 又紧又大又爽精品一区二区| 欧美吻胸吃奶大尺度电影| 色综合天天狠狠| 五月天中文字幕一区二区| 日韩欧美中文一区| 亚洲美女啪啪| 国产999精品久久久久久| 亚洲欧美乱综合| 欧美美女视频在线观看| 欧美性色综合| 久久精品国产亚洲高清剧情介绍| 国产免费成人在线视频| 色爱区综合激月婷婷| 欧美激情综合| 毛片一区二区三区| 久久久久久免费毛片精品| 久久一区视频| 欧美另类视频在线| 久久99精品久久久| 亚洲天堂免费在线观看视频| 91精品国产免费久久综合| 1024成人| 成人综合在线观看| 亚洲成在人线在线播放| 久久久国产精品不卡| 欧美日韩精品久久久| 亚洲经典在线| 成人免费精品视频| 日韩**一区毛片| 自拍偷拍国产精品| 91精品国产一区二区三区香蕉 | 99视频日韩| bt7086福利一区国产| 日本vs亚洲vs韩国一区三区二区 | 在线免费观看欧美| 韩国精品久久久| 亚洲影院在线观看| 久久影院视频免费| 欧美综合天天夜夜久久| 精品二区视频| 成人网在线播放| 蜜臀av性久久久久av蜜臀妖精 | 亚洲制服丝袜一区| 国产欧美视频一区二区| 日韩一区二区三区四区| 久久黄色小说| 在线日韩电影| 99re视频这里只有精品| 国产综合久久久久久鬼色| 天堂蜜桃一区二区三区| 亚洲三级久久久| 久久嫩草精品久久久久| 欧美猛男gaygay网站| 在线亚洲免费| 欧美精品一区二区视频| 国产宾馆实践打屁股91| 免费观看一级欧美片| 亚洲一区二区三区小说| 亚洲欧洲精品成人久久奇米网| 日韩午夜激情免费电影| 欧美午夜免费电影| 久久国产日韩欧美| 国产情侣一区| 亚洲大胆在线| 欧美日韩三区| av在线不卡电影| 国产伦精品一区二区三区免费迷| 亚洲成av人片| 亚洲乱码国产乱码精品精小说 | 中文字幕一区二区三区四区不卡| 精品国产乱子伦一区| 欧美一区二区精品久久911| 色噜噜狠狠成人中文综合| 99精品视频免费观看视频| 国内不卡一区二区三区| 欧美凹凸一区二区三区视频| 成人免费观看视频| 国产成人福利片| 国产一区二区三区观看| 久久9热精品视频| 另类成人小视频在线| 日韩1区2区3区| 日本不卡在线视频| 视频一区在线播放| 亚洲电影一区二区三区| 亚洲综合色自拍一区| 亚洲黄色片在线观看| 亚洲黄色小视频| 亚洲一区二区三区美女| 亚洲综合色区另类av| 亚洲精品欧美激情| 亚洲三级理论片| 亚洲一级电影视频| 一区二区三区中文在线| 亚洲综合成人网| 亚洲成人免费影院| 午夜精品爽啪视频| 日本在线不卡视频| 久久99国内精品| 国精品**一区二区三区在线蜜桃| 精品一区二区免费看| 国产一区二区三区黄视频| 国产不卡视频一区| 99re8在线精品视频免费播放| 欧美精品一区二区三区在线看午夜| 国产精品多人| 亚洲人人精品| 久久一区激情|