以下代码返回给定的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?相关推荐

  1. java idwork长度_java 字符串id

    Java FutureTask import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.c ...

  2. java字符对比_Java 字符串比较

    在 Java 中,比较字符串的常用方法有 3 个:equals() 方法.equalsIgnoreCase() 方法. compareTo() 方法 1. equals() equals() 方法将逐 ...

  3. Java更好的字符串排序(字母顺序+数字大小排序)

    前端JS版排序 文章目录 目标实现排序效果 问题 思路 目标实现排序效果 2022.10.30 [修复之前整数掺杂小数的情况]调整适配 1.2.3.4栋 1.2.3.5栋情况,最新效果如下 问题 业务 ...

  4. java 包装数据类型_java中的基本数据类型和包装类型

    一.学过java的应该都知道Java有八种基本数据类型:byte,short,int,long,float,double,boolean,char. 其对应的包装类型为:Byte,Short,Inte ...

  5. java 字符处理_Java字符串处理实用代码

    您的位置:首页 - 教程 - Java - 正文 Java字符串处理实用代码 package myjava; public class Mystring { public static void ma ...

  6. java string 加密_java字符串加密解密

    java字符串加密解密 try { String test = "123456789@fdj.com"; EncryptionDecryption des = new Encryp ...

  7. java 字符 加密_Java 字符串的加密与解密

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 为了保证程序的安全,经常需要用到数据加密的方法.Java 中提供了专门用于加密运算的类和接口. 除了使用加密类和接口外,还可以通过多种方式实现字符串的加密 ...

  8. java nul 字符_Java字符串替换和NUL(NULL,ASCII 0)字符?

    用空字符替换字符中的字符甚至在Java中工作吗?我知道'\ 0'会终止一个c字符串. 这取决于你如何定义工作.是否用'\0'替换了所有出现的目标字符?绝对! String s = "food ...

  9. java string分割_java 字符串分割的三种方法(总结)

    最近在项目中遇到一个小问题,一个字符串分割成一个数组,类似String str="aaa,bbb,ccc"; 然后以","为分割符,将其分割成一个数组,用什么方 ...

最新文章

  1. 全球及中国天然肠衣行业投资盈利分析及竞争格局展望报告2022-2027年
  2. 华为手机在开发Android调试时logcat不显示输出信息的解决办法
  3. 无法联系上证书的吊销服务器,CA服务器搭建问题,日志分析---吊销功能无法检查证书的吊销...
  4. Node.js Up and Runing 学习日记(八)
  5. python生成树状图_python 生成 树状结构
  6. java 插件开发 互相依赖_java – Eclipse插件开发:有没有办法控制有关我的插件缺少依赖项的安装程序消息?...
  7. zynq linux网口不通,已解决: ZYNQ 7035以太网口无法连通 - Community Forums
  8. python3callable使用_python --- Python中的callable 函数
  9. 在线免费下载音乐网站源码,支持在线播放
  10. Qt 5 下载与安装详解
  11. 计算机二级c选择题题库,全国计算机二级C选择题题库套
  12. 电力线载波 Prime PLC 通讯技术简介
  13. Java练习题——方法(基础版)
  14. 码云zheng项目介绍
  15. 先搞清楚这些问题,简历上再写你熟悉Java!
  16. 钢筋计数VOC数据集
  17. 打印机用计算机名慢,“电脑连上打印机就超级慢”的解决方案
  18. pytorch 调参
  19. 2023年全国最新会计专业技术资格精选真题及答案20
  20. 树莓派4 安装 UbuntuServer20.04.1X64 位系统 配置 wify

热门文章

  1. horizon client长时间不操作不断开_动挡操作禁忌,伤车只在一瞬间!否则变速箱会提前...
  2. spring boot 整合web开发(二)
  3. go mod导入本地包的正确引入方法:require + replace
  4. Ansible自动化运维企业实际应用场景分析
  5. Go gin框架:helloworld
  6. 【网址收藏】k8s PLEG介绍及不健康问题排查
  7. K8S报错:controller-manager Unhealthy Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252
  8. linux常用命令:系统目录说明及命令ls,cp,touch,history,gparted分区
  9. oracle jvm规范官网下载及相关书籍推荐
  10. 【代码】synchronized是可重入锁并且多个sync代码块顺序执行