日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

詳解Java的橋接方法

瀏覽:21日期: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
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久精品毛片| 亚洲精品在线影院| 亚洲18在线| 欧美成人一二区| 激情综合激情| 香蕉久久一区| 亚洲一级网站| 亚洲欧洲免费| 日韩国产综合| 中文字幕中文字幕精品| 97精品一区| 欧美日韩激情| 日韩天堂在线| 亚洲精品激情| 日韩欧美1区| 久久高清一区| 精品免费视频| 中文字幕日韩欧美精品高清在线| 久久精品亚洲| 天堂俺去俺来也www久久婷婷| 老司机免费视频一区二区| 美女久久99| 在线一区av| 中文字幕亚洲影视| 老司机免费视频一区二区三区| 午夜精品成人av| 国产麻豆精品| 欧美视频久久| 久久国产日韩欧美精品| 亚洲人成高清| 日韩动漫一区| 不卡一区综合视频| 久久久久久久久久久9不雅视频| 亚洲精品无吗| 裤袜国产欧美精品一区| 国产欧美日韩一级| 中文字幕一区二区三区四区久久 | 成人亚洲欧美| 蜜臀av免费一区二区三区| 国产欧美精品| 亚洲欧美专区| 国产婷婷精品| 国产91一区| 国产欧美高清| 日韩国产欧美一区二区三区| 欧美精品一区二区三区精品| 91免费精品| 精品国产黄a∨片高清在线| 日韩一区二区三区高清在线观看 | 日本99精品| 一二三区精品| 一区二区三区午夜视频| 欧美在线资源| 黄色成人91| 久久亚洲专区| 精品久久久中文字幕| 国产精品1区| 红杏一区二区三区| 国产在视频一区二区三区吞精| 久久精品国产99国产| 欧美精品不卡| 国产传媒av在线| 久久久久国产一区二区| 日韩精品欧美成人高清一区二区| 国产精品99一区二区| 999国产精品| 亚洲在线观看| 日韩高清国产一区在线| 国产精品调教| 福利在线免费视频| 亚洲美女久久| 亚洲一区二区三区高清不卡| av中文字幕在线观看第一页| 国产日产精品_国产精品毛片| 丝袜亚洲精品中文字幕一区| 色婷婷精品视频| 日韩精品1区| yellow在线观看网址| 综合一区在线| 深夜福利亚洲| 精品国产乱码久久久久久樱花| 久久精品国内一区二区三区水蜜桃| 久久天堂影院| 欧美精品国产一区| 日韩不卡在线观看日韩不卡视频| 亚洲女人av| 少妇高潮一区二区三区99| 国产亚洲精品v| 国产在线日韩| 久久av在线| 丝袜a∨在线一区二区三区不卡| 国产亚洲高清视频| 蜜桃视频一区二区三区| 日本精品影院| 亚洲免费成人| 亚洲区国产区| 国产精品日韩精品中文字幕| 鲁大师精品99久久久| 激情91久久| 青青国产精品| 国产精品一区二区三区美女| 狠狠久久婷婷| 亚洲三级精品| 精品国产亚洲一区二区三区在线| 日本一区二区三区中文字幕| 国产精品一区亚洲| 欧美xxxx中国| 国产模特精品视频久久久久| 亚洲免费播放| 欧美一级二级视频| 青青青免费在线视频| 久久精品青草| 国产日韩一区二区三区在线| 精品日本视频| 91中文字幕精品永久在线| 中文一区在线| а√天堂8资源中文在线| 99xxxx成人网| 日韩精品dvd| 91精品国产自产在线观看永久∴ | 国产精品永久| 97人人精品| 四虎成人精品一区二区免费网站| 成人三级高清视频在线看| 最新中文字幕在线播放| 久久亚洲色图| 欧美日韩一二| 国产精品nxnn| 蜜桃一区二区三区在线观看| 久久中文精品| 日本伊人久久| 另类亚洲自拍| 日韩免费在线| 精品丝袜久久| 综合一区在线| 日本少妇一区| 色综合五月天| 久久久久亚洲精品中文字幕| 视频在线观看一区| 精品视频91| 91成人在线网站| 精品国产乱码久久久| 免费av一区| 国产精品手机在线播放| 久久免费精品| 日韩影院在线观看| 亚洲福利一区| 亚洲二区精品| 激情自拍一区| 日韩av福利| 精品国产一区二区三区2021| 欧美精品国产| 欧洲亚洲一区二区三区| 精品99在线| 亚洲黄色影院| 国产精品一区三区在线观看| 91亚洲一区| 亚洲天堂av资源在线观看| 久久99国产精品视频| 在线日韩一区| 国产精品夜夜夜| 午夜久久tv| 国产成人精品999在线观看| 亚洲欧美高清| 精品中文字幕一区二区三区四区| 亚洲精品国产嫩草在线观看| 在线精品观看| 久久精品123| 免费看一区二区三区| 日韩中文字幕91| 日韩毛片在线| 精品久久99| 国产精品亚洲欧美一级在线| 亚州av乱码久久精品蜜桃| 日本午夜精品| 亚洲三区欧美一区国产二区| 久久精品国产在热久久| 亚洲视频国产精品| 色婷婷精品视频| 国产欧美一区二区三区精品观看| 国产v综合v| 久久婷婷激情| 欧美亚洲人成在线| 亚洲精一区二区三区| 免费观看久久av| 神马午夜久久| 色老板在线视频一区二区| 97国产成人高清在线观看| 美女久久精品| 岛国av在线网站| 精品国产美女a久久9999| 国产精品白浆| 国产一区二区三区四区五区传媒| 欧美亚洲一区二区三区| 久久亚洲电影| 日韩在线观看一区二区| 亚洲影院天堂中文av色| 在线观看亚洲精品福利片| 免费看日韩精品| 日韩在线观看中文字幕|