日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jdk1.7 String switch的实现

發(fā)布時(shí)間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jdk1.7 String switch的实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

對于int的switch,jvm是用tableswitch和lookupswitch來實(shí)現(xiàn)的,jdk1.7 switch增加了對string的支持,那么底層是如何實(shí)現(xiàn)的呢?是否增加了新的指令或是否給某些指令增加了新的含義?

?

?

看這樣一個(gè)程序:

?

Java代碼??
  • public?class?Test?{?????
  • ????public?static?void?main(String[]?args)?{????
  • ????????String?name?=?"b";??
  • ????????int?value?=?0;??
  • ????????switch(name)?{??
  • ????????????case?"a":??
  • ????????????????value?=?1;??
  • ????????????????break;??
  • ????????????case?"b":??
  • ????????????????value?=?2;??
  • ????????????????break;??
  • ????????????case?"c":??
  • ????????????????value?=?3;??
  • ????????????????break;??
  • ????????????case?"d":??
  • ????????????????value?=?4;??
  • ????????????????break;??
  • ????????????case?"e":??
  • ????????????????value?=?5;??
  • ????????????????break;??
  • ????????????default:??
  • ????????????????value?=?6;??
  • ????????}??
  • ????????System.out.println(value);??
  • ????}????
  • }??
  • ?

    javap -c Test得出的結(jié)果為:

    ?

    ?

    Java代碼??
  • public?static?void?main(java.lang.String[]);??
  • ??Code:??
  • ?????0:?ldc???????????#2??????????????????//?String?b??
  • ?????2:?astore_1????????????????????//將"b"賦值給name??
  • ?????3:?iconst_0????????????????????//將0入棧??
  • ?????4:?istore_2????????????????????//將0賦值給value??
  • ?????5:?aload_1?????????????????//將name(即"b")入棧??
  • ?????6:?astore_3????????????????????//將name(即"b")賦值給一個(gè)編譯器生成的變量,記為tmpName(tmpName此時(shí)也是"b")??
  • ?????7:?iconst_m1???????????????????//將-1入棧??
  • ?????8:?istore????????4?????????//將-1賦值給一個(gè)編譯器生成的變量,記為m1??
  • ????10:?aload_3?????????????????//將tmpName(即"b")入棧??
  • ????11:?invokevirtual?#3??????????????????//?Method?java/lang/String.hashCode:()I???????調(diào)用tmpName的hashCode方法("b".hashCode(),得結(jié)果98)??
  • ????14:?tableswitch???{?//?97?to?101????????//根據(jù)hashCode的值到不同的分支??
  • ??????????????????97:?48??
  • ??????????????????98:?63????????????????????//這里走到這個(gè)分支,跳轉(zhuǎn)到63??
  • ??????????????????99:?78??
  • ?????????????????100:?93??
  • ?????????????????101:?108??
  • ?????????????default:?120??
  • ????????}??
  • ????48:?aload_3??
  • ????49:?ldc???????????#4??????????????????//?String?a??
  • ????51:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)Z??
  • ????54:?ifeq??????????120??
  • ????57:?iconst_0??
  • ????58:?istore????????4??
  • ????60:?goto??????????120??
  • ????63:?aload_3?????????????????????????//從14跳轉(zhuǎn)到了這里,將tmpName(即"b")入棧??
  • ????64:?ldc???????????#2??????????????????//?String?b???????將"b"入棧??
  • ????66:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)Z?????
  • ????????????????????????????????????//比較tmpName和"b",如果相等,將1入棧,不等將0入棧.這里是相等的,入棧的為1??
  • ????69:?ifeq??????????120???????????????????//從棧頂取出比較結(jié)果,如果等于0,就跳到120,如果不等于0就繼續(xù)下面的指令,這里顯然不等于0??
  • ????72:?iconst_1????????????????????????????//將1入棧??
  • ????73:?istore????????4?????????????????//將1存儲到m1中??
  • ????75:?goto??????????120???????????????????//跳到120??
  • ????78:?aload_3??
  • ????79:?ldc???????????#6??????????????????//?String?c??
  • ????81:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)Z??
  • ????84:?ifeq??????????120??
  • ????87:?iconst_2??
  • ????88:?istore????????4??
  • ????90:?goto??????????120??
  • ????93:?aload_3??
  • ????94:?ldc???????????#7??????????????????//?String?d??
  • ????96:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)Z??
  • ????99:?ifeq??????????120??
  • ???102:?iconst_3??
  • ???103:?istore????????4??
  • ???105:?goto??????????120??
  • ???108:?aload_3??
  • ???109:?ldc???????????#8??????????????????//?String?e??
  • ???111:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)Z??
  • ???114:?ifeq??????????120??
  • ???117:?iconst_4??
  • ???118:?istore????????4??
  • ???120:?iload?????????4?????????????????//將m1(即73行存進(jìn)去的1)的值入棧??
  • ???122:?tableswitch???{?//?0?to?4?????????????
  • ???????????????????0:?156??
  • ???????????????????1:?161???????????????????//這里走1這個(gè)分支,跳到161??
  • ???????????????????2:?166??
  • ???????????????????3:?171??
  • ???????????????????4:?176??
  • ?????????????default:?181??
  • ????????}??
  • ???156:?iconst_1??
  • ???157:?istore_2??
  • ???158:?goto??????????184??
  • ???161:?iconst_2????????????????????//將2入棧??
  • ???162:?istore_2????????????????????//將2存儲到value??
  • ???163:?goto??????????184???????????//跳轉(zhuǎn)到184進(jìn)行打印輸出??
  • ???166:?iconst_3??
  • ???167:?istore_2??
  • ???168:?goto??????????184??
  • ???171:?iconst_4??
  • ???172:?istore_2??
  • ???173:?goto??????????184??
  • ???176:?iconst_5??
  • ???177:?istore_2??
  • ???178:?goto??????????184??
  • ???181:?bipush????????6??
  • ???183:?istore_2??
  • ???184:?getstatic?????#9??????????????????//?Field?java/lang/System.out:Ljava/io/PrintStream;??
  • ???187:?iload_2??
  • ???188:?invokevirtual?#10?????????????????//?Method?java/io/PrintStream.println:(I)V??
  • ???191:?return??
  • ?

    ?

    在這一堆指令中我們發(fā)現(xiàn),jdk1.7并沒有新指令來處理string switch,還是繼續(xù)用lookupswitch和tableswitch兩個(gè)指令來處理的,也沒有擴(kuò)展這兩個(gè)指令,它們還是只能處理int。

    ?

    ?

    在11行,我們看到調(diào)用了需要switch的string的hashCode方法,并對該hashCode進(jìn)行switch,并跳轉(zhuǎn)到相應(yīng)的處理指令。跳到新的指令處我們發(fā)現(xiàn)這里(63行)將待switch的變量(name)與case中的值("b")equals了一下。這樣做是為了避免不同的string有相同的hashCode,確定equals返回true后,編譯器生成了一個(gè)處理value的switch,源碼里有多少個(gè)case編譯器生成的tableswitch就有多少個(gè)分支,最終會找到相應(yīng)的處理分支完成string switch的處理。

    ?

    ?

    接下來,看一個(gè)不同string hashCode相等的版本:

    ?

    buzzards與righto的hashCode相等

    hierarch與crinolines的hashCode相等

    ?

    這里選擇buzzards和righto

    ?

    ?

    Java代碼??
  • public?class?Test?{?????
  • ????public?static?void?main(String[]?args)?{????
  • ????????String?name?=?"buzzards";??
  • ????????int?value?=?0;??
  • ????????switch(name)?{??
  • ????????????case?"buzzards":??
  • ????????????????value?=?1;??
  • ????????????????break;??
  • ????????????case?"righto":??
  • ????????????????value?=?2;??
  • ????????????????break;??
  • ????????????default:??
  • ????????????????value?=?6;??
  • ????????}??
  • ????????System.out.println(value);??
  • ????}????
  • }??
  • ?

    ?

    字節(jié)碼:

    ?

    Java代碼??
  • public?static?void?main(java.lang.String[]);??
  • ??Code:??
  • ?????0:?ldc???????????#2??????????????????//?String?buzzards??
  • ?????2:?astore_1??
  • ?????3:?iconst_0??
  • ?????4:?istore_2??
  • ?????5:?aload_1??
  • ?????6:?astore_3??
  • ?????7:?iconst_m1??
  • ?????8:?istore????????4??
  • ????10:?aload_3??
  • ????11:?invokevirtual?#3??????????????????//?Method?java/lang/String.hashCode:()I??
  • ????14:?lookupswitch??{?//?1??
  • ??????????-931102253:?32??
  • ?????????????default:?59??
  • ????????}??
  • ????32:?aload_3??
  • ????33:?ldc???????????#4??????????????????//?String?righto??
  • ????35:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)??
  • ????38:?ifeq??????????47??
  • ????41:?iconst_1??
  • ????42:?istore????????4??
  • ????44:?goto??????????59??
  • ????47:?aload_3??
  • ????48:?ldc???????????#2??????????????????//?String?buzzards??
  • ????50:?invokevirtual?#5??????????????????//?Method?java/lang/String.equals:(Ljava/lang/Object;)??
  • ????53:?ifeq??????????59??
  • ????56:?iconst_0??
  • ????57:?istore????????4??
  • ????59:?iload?????????4??
  • ????61:?lookupswitch??{?//?2??
  • ???????????????????0:?88??
  • ???????????????????1:?93??
  • ?????????????default:?98??
  • ????????}??
  • ????88:?iconst_1??
  • ????89:?istore_2??
  • ????90:?goto??????????101??
  • ????93:?iconst_2??
  • ????94:?istore_2??
  • ????95:?goto??????????101??
  • ????98:?bipush????????6??
  • ???100:?istore_2??
  • ???101:?getstatic?????#6??????????????????//?Field?java/lang/System.out:Ljava/io/PrintStream;??
  • ???104:?iload_2??
  • ???105:?invokevirtual?#7??????????????????//?Method?java/io/PrintStream.println:(I)V??
  • ???108:?return??
  • ?

    ?

    ?

    這里我們看到兩個(gè)字符串都跳到32行,首先跟"righto"比較,如果不相等則跳到47行比較buzzards。

    轉(zhuǎn)載于:https://www.cnblogs.com/zhangyfr/p/8493950.html

    總結(jié)

    以上是生活随笔為你收集整理的jdk1.7 String switch的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。