Java中switch支持字符串原理

    Java7之后的版本才开始支持switch字符串,但是内部实现case还是基于整形变量的匹配。下面编写一个使用switch字符串的sample来看下。

    

package org.sun.sample.pojo;

/**
 * Created by aron on 16-4-11.
 */
public class SwitchSample {

    public static final String RED= "RED";
    public static final String BLUE= "BLUE";
    public static final String GREEN= "GREEN";


    public void executeSwitch(String color) {
        switch (color) {
            case SwitchSample.RED:
                System.out.println(color);
                break;
            case SwitchSample.BLUE:
                System.out.println(color);
                break;
            case SwitchSample.GREEN:
                System.out.println(color);
                break;
            default:
                System.out.println("not match !!!");
        }
    }

}



    这个类被反编译之后的代码是:



//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.sun.sample.pojo;

public class SwitchSample {
    public static final String RED = "RED";
    public static final String BLUE = "BLUE";
    public static final String GREEN = "GREEN";

    public SwitchSample() {
    }

    public void executeSwitch(String color) {
        byte var3 = -1;
        switch(color.hashCode()) {
        case 81009:
            if(color.equals("RED")) {
                var3 = 0;
            }
            break;
        case 2041946:
            if(color.equals("BLUE")) {
                var3 = 1;
            }
            break;
        case 68081379:
            if(color.equals("GREEN")) {
                var3 = 2;
            }
        }

        switch(var3) {
        case 0:
            System.out.println(color);
            break;
        case 1:
            System.out.println(color);
            break;
        case 2:
            System.out.println(color);
            break;
        default:
            System.out.println("not match !!!");
        }

    }
}



    可以看出来,反编译之后case后面跟着的还是整型变量。那这些整型变量是怎么来的呢?看下字节码会更清楚些。



Classfile /home/aron/workspace/idea/sun-sample/target/classes/org/sun/sample/pojo/SwitchSample.class
  Last modified 2016-4-11; size 975 bytes
  MD5 checksum 77db58f6c9ecac22549a85e042043490
  Compiled from "SwitchSample.java"
public class org.sun.sample.pojo.SwitchSample
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #11.#31        // java/lang/Object."<init>":()V
   #2 = Methodref          #32.#33        // java/lang/String.hashCode:()I
   #3 = String             #12            // RED
   #4 = Methodref          #32.#34        // java/lang/String.equals:(Ljava/lang/Object;)Z
   #5 = String             #15            // BLUE
   #6 = String             #16            // GREEN
   #7 = Fieldref           #35.#36        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Methodref          #37.#38        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #9 = String             #39            // not match !!!
  #10 = Class              #40            // org/sun/sample/pojo/SwitchSample
  #11 = Class              #41            // java/lang/Object
  #12 = Utf8               RED
  #13 = Utf8               Ljava/lang/String;
  #14 = Utf8               ConstantValue
  #15 = Utf8               BLUE
  #16 = Utf8               GREEN
  #17 = Utf8               <init>
  #18 = Utf8               ()V
  #19 = Utf8               Code
  #20 = Utf8               LineNumberTable
  #21 = Utf8               LocalVariableTable
  #22 = Utf8               this
  #23 = Utf8               Lorg/sun/sample/pojo/SwitchSample;
  #24 = Utf8               executeSwitch
  #25 = Utf8               (Ljava/lang/String;)V
  #26 = Utf8               color
  #27 = Utf8               StackMapTable
  #28 = Class              #42            // java/lang/String
  #29 = Utf8               SourceFile
  #30 = Utf8               SwitchSample.java
  #31 = NameAndType        #17:#18        // "<init>":()V
  #32 = Class              #42            // java/lang/String
  #33 = NameAndType        #43:#44        // hashCode:()I
  #34 = NameAndType        #45:#46        // equals:(Ljava/lang/Object;)Z
  #35 = Class              #47            // java/lang/System
  #36 = NameAndType        #48:#49        // out:Ljava/io/PrintStream;
  #37 = Class              #50            // java/io/PrintStream
  #38 = NameAndType        #51:#25        // println:(Ljava/lang/String;)V
  #39 = Utf8               not match !!!
  #40 = Utf8               org/sun/sample/pojo/SwitchSample
  #41 = Utf8               java/lang/Object
  #42 = Utf8               java/lang/String
  #43 = Utf8               hashCode
  #44 = Utf8               ()I
  #45 = Utf8               equals
  #46 = Utf8               (Ljava/lang/Object;)Z
  #47 = Utf8               java/lang/System
  #48 = Utf8               out
  #49 = Utf8               Ljava/io/PrintStream;
  #50 = Utf8               java/io/PrintStream
  #51 = Utf8               println
{
  public static final java.lang.String RED;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: String RED

  public static final java.lang.String BLUE;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: String BLUE

  public static final java.lang.String GREEN;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: String GREEN

  public org.sun.sample.pojo.SwitchSample();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lorg/sun/sample/pojo/SwitchSample;

  public void executeSwitch(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=2
         0: aload_1
         1: astore_2
         2: iconst_m1
         3: istore_3
         4: aload_2
         5: invokevirtual #2                  // Method java/lang/String.hashCode:()I
         8: lookupswitch  { // 3
                   81009: 44
                 2041946: 58
                68081379: 72
                 default: 83
            }
        44: aload_2
        45: ldc           #3                  // String RED
        47: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        50: ifeq          83
        53: iconst_0
        54: istore_3
        55: goto          83
        58: aload_2
        59: ldc           #5                  // String BLUE
        61: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        64: ifeq          83
        67: iconst_1
        68: istore_3
        69: goto          83
        72: aload_2
        73: ldc           #6                  // String GREEN
        75: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        78: ifeq          83
        81: iconst_2
        82: istore_3
        83: iload_3
        84: tableswitch   { // 0 to 2
                       0: 112
                       1: 122
                       2: 132
                 default: 142
            }
       112: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       115: aload_1
       116: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       119: goto          150
       122: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       125: aload_1
       126: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       129: goto          150
       132: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       135: aload_1
       136: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       139: goto          150
       142: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       145: ldc           #9                  // String not match !!!
       147: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       150: return
      LineNumberTable:
        line 14: 0
        line 16: 112
        line 17: 119
        line 19: 122
        line 20: 129
        line 22: 132
        line 23: 139
        line 25: 142
        line 27: 150
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0     151     0  this   Lorg/sun/sample/pojo/SwitchSample;
            0     151     1 color   Ljava/lang/String;
      StackMapTable: number_of_entries = 9
        frame_type = 253 /* append */
          offset_delta = 44
          locals = [ class java/lang/String, int ]
        frame_type = 13 /* same */
        frame_type = 13 /* same */
        frame_type = 10 /* same */
        frame_type = 28 /* same */
        frame_type = 9 /* same */
        frame_type = 9 /* same */
        frame_type = 9 /* same */
        frame_type = 249 /* chop */
          offset_delta = 7
}
SourceFile: "SwitchSample.java"

    可以看出来,这些整型变量是Method java/lang/String.hashCode,是字符串的hashCode值。在查看下hashCode的源代码即可发现hashCode是怎么生成的了。

    

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }


    所以81009就是"RED".hashCode()值。写短代码测试下。

package org.sun.sample;

/**
 * 启动类
 */
public class Bootstrap {

    public static void main(String[] args) {
        System.out.println(new String("RED").hashCode());
    }

}



    可以看到最后的输出是 81009,验证了上面的猜测。

转载于:https://my.oschina.net/netflasher/blog/656632

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值