【Java小知识】switch支持String类型的背后原理?

前言

大家都知道,从JDK 1.7开始,switch表达式开始支持String字符串,那么它是怎么实现的呢?

今天来一探究竟

分析

首先写一个小demo,如下所示,一个简单的switc语句:

public class test {
    public static void main(String[] args) {
        test("a");
    }

    public static void test(String s) {
        switch (s) {
            case "a":
                System.out.println("hello");
                break;
            case "b":
                System.out.println("world");
                break;
            default:
        }
    }
}

然后执行javap -c test.class命令,查看其汇编指令执行过程:

public class test {
  public test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String a
       2: invokestatic  #3                  // Method test:(Ljava/lang/String;)V
       5: return

  public static void test(java.lang.String);
    Code:
       0: aload_0
       1: astore_1
       2: iconst_m1
       3: istore_2
       4: aload_1
       5: invokevirtual #4                  // Method java/lang/String.hashCode:()I
       8: lookupswitch  { // 2
                    97: 36
                    98: 50
               default: 61
          }
      36: aload_1
      37: ldc           #2                  // String a
      39: invokevirtual #5                  // 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           #6                  // String b
      53: invokevirtual #5                  // 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: 99
               default: 110
          }
      88: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      91: ldc           #8                  // String hello
      93: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      96: goto          110
      99: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
     102: ldc           #10                 // String world
     104: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     107: goto          110
     110: return
}

可以看出,对String对象调用了hashCode()方法,得到了一个int类型的hash值,然后用这个hash值来唯一标识这个case。

所以当匹配时:

  1. 首先调用这个字符串的hashCode()方法,获取一个hash值(int 类型),用这个hash值来匹配所有的case;
  2. 如果没有匹配成功,说明不存在;
  3. 如果匹配成功了,接着会调用字符串的equals()方法进行匹配。

注意:switch的case子句中使用的字符串也不能为null。

小结

从本质上讲,switch对字符串的支持,其实是int类型值的匹配。

发布了18 篇原创文章 · 获赞 38 · 访问量 679

猜你喜欢

转载自blog.csdn.net/wudingmei1023/article/details/103920416
今日推荐