【问题标题】:Why is this happenning with switch (Java)? [duplicate]为什么开关(Java)会发生这种情况? [复制]
【发布时间】:2013-12-09 17:55:23
【问题描述】:

很明显 switch 语句可以在 Java 中使用字符串值,类似这样:

String s="diljit"
switch(s){
 ..
 ....}

将始终编译.. sString 类型的对象.. 但另一方面 switch 语句不能接受其他类的对象?为什么会发生这种情况,我将如何用合适的答案验证这个问题..

switch 语句可以带对象吗?

【问题讨论】:

    标签: java string switch-statement


    【解决方案1】:

    switch语句可以带对象吗?

    不,您不能在 switch 语句中使用任意对象。这是在语言本身中指定的。甚至 String 也只允许从 Java 7 开始。来自JLS §14.11

    表达式的类型必须是charbyteshortintCharacterByteShortInteger、@987654333325@或@9876543324 @type (§8.9),或发生编译时错误。

    【讨论】:

    • 补充一下 Rohit 所说的,如果你想根据对象的值进行切换,你可以使用枚举来实现。将你要切换的对象的所有变量放入一个枚举中,根据枚举进行切换。
    【解决方案2】:

    String 在 java 中非常特殊。 String 设计为介于 primitiveClass 之间。

    使每个primitive 可用,java 允许(从 7 开始)String 也在 switch 中(内部使用 **equals** 方法)。

    所以String 允许切换。但不是每个Object.

    【讨论】:

      【解决方案3】:

      带有字符串的switch语句是用hashCode比较编译的,所以代码:

      switch(s){
          case "1":
          case "2":
          case "3":
      }
      

      编译后的样子:

      switch(s.hashCode()){
          case "1".hashCode():
          case "2".hashCode():
          case "3".hashCode():
      }
      

      实际上,第 7 版 JVM 并没有添加任何关于在开关中使用字符串的具体内容。只是一点编译技巧。它可以通过 hashCode() 来比较字符串,因为这个函数被覆盖并且基于对象的内容。此信息在编译时存在。 虽然它对字符串是合法的,但这种方法对于任意对象是绝对不可接受的,因为 hashCode() 返回一个随机数。

      这就是它在字节码中的样子:

      11: tableswitch   { // 49 to 51
                  49: 36        // "1".hashCode() 
                  50: 50        // "2".hashCode() 
                  51: 64        // "3".hashCode() 
             default: 75
        }
      36: aload_2       
      37: ldc           #4                  // String 1
      39: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      42: ifeq          75
      45: iconst_0      
      46: istore_3      
      47: goto          75
      50: aload_2       
      51: ldc           #6                  // String 2
      53: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      56: ifeq          75
      59: iconst_1      
      60: istore_3      
      61: goto          75
      64: aload_2       
      65: ldc           #7                  // String 3
      67: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      70: ifeq          75
      73: iconst_2      
      74: istore_3      
      75: iload_3       
      76: tableswitch   { // 0 to 2
               0: 104
               1: 104
               2: 104
         default: 104
      }
      104: return 
      

      Switch with Strings 编译为使用 int 进行 switch。如果意外地两个哈希码相等,则使用 equals() 方法比较字符串。 Compiling switches 来自 JVM 规范。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-30
        • 2010-09-22
        • 1970-01-01
        相关资源
        最近更新 更多