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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 编译开关_java – 字符串是关于开关的数字类型,并始终编译为lookupswitch?

發布時間:2024/10/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 编译开关_java – 字符串是关于开关的数字类型,并始终编译为lookupswitch? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以下代碼返回給定的String s是否等于任何其他硬編碼字符串.該方法使用switch語句來執行此操作:

public class SwitchOnString {

public static boolean equalsAny(String s) {

switch (s) {

case "string 1":

return true;

case "string 2":

return true;

default:

return false;

}

}

}

Compilation of switch statements uses the tableswitch and lookupswitch

instructions.

此外

tableswitch and lookupswitch instructions operate only on int data.

我閱讀了3.10章,但沒有找到提到的String.

間接關閉的唯一一句是:

Other numeric types must be narrowed to type int for use in a switch.

問題1:

此上下文中的String也是數字類型嗎?還是我錯過了什么?

SwitchOnString類上的javap -c顯示:

Compiled from "SwitchOnString.java"

public class playground.SwitchOnString {

public playground.SwitchOnString();

...

public static boolean equalsAny(java.lang.String);

Code:

0: aload_0

1: dup

2: astore_1

3: invokevirtual #16 // Method java/lang/String.hashCode:()I

6: lookupswitch { // 2

1117855161: 32

1117855162: 44

default: 60

}

...

}

顯然,hashCode值用作case的int-keys.這可能匹配:

The lookupswitch instruction pairs int keys (the values of the case

labels) …

繼續使用tableswitch和lookupswitch JMS說:

The tableswitch instruction is used when the cases of the switch can

be efficiently represented as indices into a table of target offsets. (…)

Where the cases of the switch are sparse, the table representation of

the tableswitch instruction becomes inefficient in terms of space. The

lookupswitch instruction may be used instead.

如果我做到了這一點,那么案例越稀疏,查找切換的可能性就越大.

問題2:

但是看一下字節碼:

兩個字符串大小是否足夠稀疏以編譯切換到lookupswitch?或者將String上的每個開關編譯為lookupswitch?

最佳答案 規范沒有說明如何編譯switch語句,這取決于編譯器.

在這方面,JVMS語句“其他數字類型必須縮小到int類型才能在交換機中使用”并不是說Java編程語言會進行這樣的轉換,也不會說String或Enum是數字類型.即long,float和double是數字類型,但是不支持在Java編程語言中將它們與switch語句一起使用.

所以語言規范說支持切換字符串,因此,編譯器必須找到一種方法將它們編譯為字節碼.使用像哈希碼這樣的不變屬性是一種常見的解決方案,但原則上,也可以使用其他屬性,如長度或任意字符.

然后,編譯器必須選擇lookupswitch或tableswitch指令.當數字不稀疏時,javac確實使用tableswitch,但僅當語句具有兩個以上的case標簽時才使用.

所以當我編譯以下方法時:

public static char two(String s) {

switch(s) {

case "a": return 'a';

case "b": return 'b';

}

return 0;

}

我明白了

public static char two(java.lang.String);

Code:

0: aload_0

1: astore_1

2: iconst_m1

3: istore_2

4: aload_1

5: invokevirtual #9 // Method java/lang/String.hashCode:()I

8: lookupswitch { // 2

97: 36

98: 50

default: 61

}

36: aload_1

37: ldc #10 // String a

39: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

42: ifeq 61

45: iconst_0

46: istore_2

47: goto 61

50: aload_1

51: ldc #12 // String b

53: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

56: ifeq 61

59: iconst_1

60: istore_2

61: iload_2

62: lookupswitch { // 2

0: 88

1: 91

default: 94

}

88: bipush 97

90: ireturn

91: bipush 98

93: ireturn

94: iconst_0

95: ireturn

但是當我編譯時,

public static char three(String s) {

switch(s) {

case "a": return 'a';

case "b": return 'b';

case "c": return 'c';

}

return 0;

}

我明白了

public static char three(java.lang.String);

Code:

0: aload_0

1: astore_1

2: iconst_m1

3: istore_2

4: aload_1

5: invokevirtual #9 // Method java/lang/String.hashCode:()I

8: tableswitch { // 97 to 99

97: 36

98: 50

99: 64

default: 75

}

36: aload_1

37: ldc #10 // String a

39: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

42: ifeq 75

45: iconst_0

46: istore_2

47: goto 75

50: aload_1

51: ldc #12 // String b

53: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

56: ifeq 75

59: iconst_1

60: istore_2

61: goto 75

64: aload_1

65: ldc #13 // String c

67: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

70: ifeq 75

73: iconst_2

74: istore_2

75: iload_2

76: tableswitch { // 0 to 2

0: 104

1: 107

2: 110

default: 113

}

104: bipush 97

106: ireturn

107: bipush 98

109: ireturn

110: bipush 99

112: ireturn

113: iconst_0

114: ireturn

目前還不清楚為什么javac做出這個選擇.雖然tableswitch與lookupswitch相比具有更高的基本占用空間(一個額外的32位字),但在字節碼中它仍然會更短,即使對于兩個案例標簽場景也是如此.

但是決策的一致性可以用第二個語句顯示,它將始終具有相同的值范圍,但僅根據標簽的數量編譯為lookupswitch或tableswitch.因此,當使用真正的稀疏值時:

public static char three(String s) {

switch(s) {

case "a": return 'a';

case "b": return 'b';

case "": return 0;

}

return 0;

}

它編譯成

public static char three(java.lang.String);

Code:

0: aload_0

1: astore_1

2: iconst_m1

3: istore_2

4: aload_1

5: invokevirtual #9 // Method java/lang/String.hashCode:()I

8: lookupswitch { // 3

0: 72

97: 44

98: 58

default: 83

}

44: aload_1

45: ldc #10 // String a

47: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

50: ifeq 83

53: iconst_0

54: istore_2

55: goto 83

58: aload_1

59: ldc #12 // String b

61: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

64: ifeq 83

67: iconst_1

68: istore_2

69: goto 83

72: aload_1

73: ldc #13 // String

75: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

78: ifeq 83

81: iconst_2

82: istore_2

83: iload_2

84: tableswitch { // 0 to 2

0: 112

1: 115

2: 118

default: 120

}

112: bipush 97

114: ireturn

115: bipush 98

117: ireturn

118: iconst_0

119: ireturn

120: iconst_0

121: ireturn

使用lookupswitch作為稀疏哈希碼,但使用tableswitch作為第二個交換機.

總結

以上是生活随笔為你收集整理的java 编译开关_java – 字符串是关于开关的数字类型,并始终编译为lookupswitch?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。