zoukankan      html  css  js  c++  java
  • switch表达式中可以用哪些类型

    switch语句是一个很容易忽略的语法点,在表达式支持的类型上也犯过很多错,今天就来整理一下

    switch语句基本定义:

    switch (表达式){
        case 值1: 
            语句体1;
            break;
        case 值2:
            语句体2;
            break;
        ...
            
        default:
            语句体n+1;
            break;
    }
    

    break在switch语句中的作用

    关于breakswitch语句的使用可以参考这篇博客https://www.cnblogs.com/EthanWong/p/13190595.html

    表达式的取值

    表达式的取值类型

    1. 在JDK6及以前,表达式只能是一个常量表达式或枚举常量。所以表达式的取值可以是:
      • byteshortintchar四种基本类型,以及其包装类型
      • Enum枚举类型
    2. 在JDK7以后新增支持String类型

    编译器对表达式取值的处理

    虽然随着JDK版本迭代,支持的新类型越来越多,但是在编译的字节码层次,switch语句还是只能支持基本的四种类型。

    1. 基本类型的处理

      int数据类型

      int a = 2;
      switch (a)
          {
              case 1: 
                  System.out.println("first");
                  break;
      
              case 2: 
                  System.out.println("second");
                  break;
      
              case 3: 
                  System.out.println("second");
                  break;
      
              default:
                  System.out.println("null");
                  break;
          }
      

      反编译后的代码

      byte byte0 = 2;
      		switch (byte0)
      		{
      		case 1: // '01'
      			System.out.println("first");
      			break;
      
      		case 2: // '02'
      			System.out.println("second");
      			break;
      
      		case 3: // '03'
      			System.out.println("second");
      			break;
      
      		default:
      			System.out.println("null");
      			break;
      		}
      

      ​ 其实从这里就可以看出,正是因为intbytecharshort之间可以隐式转换。所以可以直接支持其对应的四种包装类型

      char类型的处理

      char c = '2';
      switch (c)
          {
              case '1': 
                  System.out.println("first");
                  break;
      
              case '2': 
                  System.out.println("second");
                  break;
      
              case '3': 
                  System.out.println("second");
                  break;
      
              default:
                  System.out.println("null");
                  break;
          }
      

      反编译后的代码:

      byte byte0 = 50;
      		switch (byte0)
      		{
      		case 49: // '1'
      			System.out.println("first");
      			break;
      
      		case 50: // '2'
      			System.out.println("second");
      			break;
      
      		case 51: // '3'
      			System.out.println("second");
      			break;
      
      		default:
      			System.out.println("null");
      			break;
      		}
      

      从代码来看,底层是通过比较字符的ASCII码来进行判断的。

    2. 包装类型的处理

      Integer I = 4;
      switch (I)
          {
              case 1: 
                  System.out.println("first");
                  break;
      
              case 2: 
                  System.out.println("second");
                  break;
      
              case 3: 
                  System.out.println("second");
                  break;
      
              default:
                  System.out.println("null");
                  break;
          }
      

      经过反编译后的代码是

      Integer integer = Integer.valueOf(4);
      		switch (integer.intValue())
      		{
      		case 1: // '01'
      			System.out.println("first");
      			break;
      
      		case 2: // '02'
      			System.out.println("second");
      			break;
      
      		case 3: // '03'
      			System.out.println("second");
      			break;
      
      		default:
      			System.out.println("null");
      			break;
      		}
      

      从反编译的代码中可以看出,Integer装箱的时候自动调用Integervalueof(int)方法,拆箱的时候是自动调用IntegerintValue方法。对应到其他包装类型和Integer也类似。

    3. 枚举类型的处理

      public enum ColorEnum{
          RED,GREEN,YELLOW;
      }
      
      public class EnumTest{
          public static void main(String args[]){
              ColorEnum color = ColorEnum.YELLOW;
              switch(color){
                  case RED:
                      System.out.println("Stop");
                      break;
                  case GREEN:
                      System.out.println("Pass");
                      break;
                  case YELLOW:
                      System.out.println("Wait");
                      break;
                  default:
                      System.out.println("null");
                      break;
              }
          }
      }
      

      反编译:

      // Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
      // Jad home page: http://kpdus.tripod.com/jad.html
      // Decompiler options: packimports(3) fieldsfirst ansi space 
      // Source File Name:   EnumTest.java
      
      import java.io.PrintStream;
      
      public class EnumTest
      {
      
      	public EnumTest()
      	{
      	}
      
      	public static void main(String args[])
      	{
      		ColorEnum colorenum = ColorEnum.YELLOW;
      		static class 1
      		{
      
      			static final int $SwitchMap$ColorEnum[];
      			//自动生成int数组,通过编号来表示枚举
      			static 
      			{
      				$SwitchMap$ColorEnum = new int[ColorEnum.values().length];
      				try
      				{
      					$SwitchMap$ColorEnum[ColorEnum.RED.ordinal()] = 1;
      				}
      				catch (NoSuchFieldError nosuchfielderror) { }
      				try
      				{
      					$SwitchMap$ColorEnum[ColorEnum.GREEN.ordinal()] = 2;
      				}
      				catch (NoSuchFieldError nosuchfielderror1) { }
      				try
      				{
      					$SwitchMap$ColorEnum[ColorEnum.YELLOW.ordinal()] = 3;
      				}
      				catch (NoSuchFieldError nosuchfielderror2) { }
      			}
      		}
      
      		switch (1..SwitchMap.ColorEnum[colorenum.ordinal()])
      		{
      		case 1: // '01'
      			System.out.println("Stop");
      			break;
      
      		case 2: // '02'
      			System.out.println("Pass");
      			break;
      
      		case 3: // '03'
      			System.out.println("Wait");
      			break;
      
      		default:
      			System.out.println("null");
      			break;
      		}
      	}
      }
      

      从反编译的代码可以看出,底层通过创建$SwitchMap$ColorEnum[]int数组,并通过数组的编号来表示枚举。

    4. String类型的处理

      public class StringTest{
          public static void main (String args[]){
              String s = "RED";
              switch(s){
                  case RED:
                      System.out.println("红色");
                      break;
                  case GREEN:
                      System.out.println("绿色");
                      break;
                  case YELLOW:
                      System.out.println("黄色");
                      break;
                  default:
                      System.out.println("null");
                      break;
              }
          }
      }
      

      反编译后:

      // Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
      // Jad home page: http://kpdus.tripod.com/jad.html
      // Decompiler options: packimports(3) fieldsfirst ansi space 
      // Source File Name:   StringTest.java
      
      import java.io.PrintStream;
      
      public class StringTest
      {
      
      	public StringTest()
      	{
      	}
      
      	public static void main(String args[])
      	{
      		String s = "RED";
      		String s1 = s;//创建string对象
      		byte byte0 = -1;
      		switch (s1.hashCode())
      		{
      		case 81009: //string常量用hash值表示
      			if (s1.equals("RED")) //避免hash碰撞,用equals辅助判断
      				byte0 = 0;
      			break;
      
      		case 68081379: 
      			if (s1.equals("GREEN"))
      				byte0 = 1;
      			break;
      
      		case -1680910220: 
      			if (s1.equals("YELLOW"))
      				byte0 = 2;
      			break;
      		}
      		switch (byte0)
      		{
      		case 0: // ''
      			System.out.println("红色");
      			break;
      
      		case 1: // '01'
      			System.out.println("绿色");
      			break;
      
      		case 2: // '02'
      			System.out.println("黄色");
      			break;
      
      		default:
      			System.out.println("null");
      			break;
      		}
      	}
      }
      

      从代码中可以看出,在对String类型的处理中,是通过对常量的hash值和equals方法来判断比较。

  • 相关阅读:
    Application.Exit()结束程序,但线程还在的解决方法
    Myeclipse2014 SVN安装方法以及项目上传到svn服务器
    MyEclipse中把JSP默认编码改为UTF-8
    005_MyEclipse编码设置
    laravel5.2学习资源
    wechat-php-sdk
    微信邀请卡的开发
    微信JS-SDK实际分享功能
    每个Linux新手都应该记住的10个基本Linux命令
    Linux下定时备份数据库
  • 原文地址:https://www.cnblogs.com/EthanWong/p/13194447.html
Copyright © 2011-2022 走看看