前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >switch表达式中可以用哪些类型

switch表达式中可以用哪些类型

作者头像
归思君
发布2023-10-16 08:47:56
2640
发布2023-10-16 08:47:56
举报
文章被收录于专栏:归思君的技术博客

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

switch语句基本定义:

代码语言:javascript
复制
switch (表达式){
    case 值1: 
        语句体1;
        break;
    case 值2:
        语句体2;
        break;
    ...
        
    default:
        语句体n+1;
        break;
}

break在switch语句中的作用

关于breakswitch语句的使用可以参考这篇博客https://cloud.tencent.com/developer/article/2342385

表达式的取值

表达式的取值类型

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

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

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

基本类型的处理

int**数据类型**

代码语言:javascript
复制
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;
    }

反编译后的代码

代码语言:javascript
复制
byte byte0 = 2;
		switch (byte0)
		{
		case 1: // '\001'
			System.out.println("first");
			break;

		case 2: // '\002'
			System.out.println("second");
			break;

		case 3: // '\003'
			System.out.println("second");
			break;

		default:
			System.out.println("null");
			break;
		}

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

char**类型的处理**

代码语言:javascript
复制
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;
    }

反编译后的代码:

代码语言:javascript
复制
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码来进行判断的。

包装类型的处理

代码语言:javascript
复制
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;
    }

经过反编译后的代码是

代码语言:javascript
复制
Integer integer = Integer.valueOf(4);
		switch (integer.intValue())
		{
		case 1: // '\001'
			System.out.println("first");
			break;

		case 2: // '\002'
			System.out.println("second");
			break;

		case 3: // '\003'
			System.out.println("second");
			break;

		default:
			System.out.println("null");
			break;
		}

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

枚举类型的处理

代码语言:javascript
复制
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;
        }
    }
}

反编译:

代码语言:javascript
复制
// 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: // '\001'
			System.out.println("Stop");
			break;

		case 2: // '\002'
			System.out.println("Pass");
			break;

		case 3: // '\003'
			System.out.println("Wait");
			break;

		default:
			System.out.println("null");
			break;
		}
	}
}

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

String类型的处理

代码语言:javascript
复制
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;
        }
    }
}

反编译后:

代码语言:javascript
复制
// 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: // '\0'
			System.out.println("红色");
			break;

		case 1: // '\001'
			System.out.println("绿色");
			break;

		case 2: // '\002'
			System.out.println("黄色");
			break;

		default:
			System.out.println("null");
			break;
		}
	}
}

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • switch语句基本定义:
    • break在switch语句中的作用
    • 表达式的取值
      • 表达式的取值类型
        • 编译器对表达式取值的处理
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档