在Switch中可以使用的类型有枚举、字符串类型与整形int类型,下面来具体看这几个类型。

1、switch为枚举类型

枚举类:

enum Fruit {
    APPLE,ORINGE
}  

调用javac生成的代码如下:

enum Fruit{
	private <init>(/*synthetic*/ String $enum$name,
			       /*synthetic*/ int $enum$ordinal) {
	    super($enum$name, $enum$ordinal);
	}
	 /*public static final*/ APPLE /* = new Fruit("APPLE", 0) */
	 /*public static final*/ ORINGE /* = new Fruit("ORINGE", 1) */
	 /*synthetic*/ private static final Fruit[] $VALUES =
	                     new Fruit[]{Fruit.APPLE, Fruit.ORINGE}
	public static Fruit[] values() {
	    return (Fruit[])$VALUES.clone();
	}
	public static Fruit valueOf(String name) {
	    return (Fruit)Enum.valueOf(Fruit.class, name);
	}
}

Enum在Java中也被当作一个类来处理,并且Enum也算是Java中的语法糖,主要通过Javac中的Lower类来处理枚举这个语法糖的。

查看javac的英文说明,如下:

This map gives a translation table to be used for enum switches.

For each enum that appears as the type of a switch expression, we maintain an EnumMapping(举例) to assist in the translation, as exemplified by the following example:

we translate

Fruit fruit = Fruit.APPLE;
switch (fruit) {
case APPLE:
    System.out.println("apple");
    break;
case ORANGE:
    System.out.println("orange");
    break;
default:
    System.out.println("unknow");
}

into

switch (com.test19.TestEnumClass$1.$SwitchMap$com$test19$Fruit[(fruit).ordinal()]) {
case 1:
    System.out.println("apple");
    break;

case 2:
    System.out.println("orange");
    break;

default:
    System.out.println("unknow");

}

with the auxiliary table initialized as follows:

/*synthetic*/ class TestEnumClass$1 {
		    /*synthetic*/ static final int[] $SwitchMap$com$test19$Fruit = new int[Fruit.values().length];
		    static {
		        try {
		            com.test19.TestEnumClass$1.$SwitchMap$com$test19$Fruit[Fruit.APPLE.ordinal()] = 1;
		        } catch (NoSuchFieldError ex) {
		        }
		        try {
		            com.test19.TestEnumClass$1.$SwitchMap$com$test19$Fruit[Fruit.ORANGE.ordinal()] = 2;
		        } catch (NoSuchFieldError ex) {
		        }
		    }
}

class EnumMapping provides mapping data and support methods for this translation.

2、switch为字符串类型

下面继续来看switch对于字符串的处理。

The general approach used is to translate a single string switch statement into a series of two chained switch statements:

使用的一般方法是将一个字符串类型的switch语句翻译为两个switch语句:

the first a synthesized statement switching on the argument string's hash value and
computing a string's position in the list of original case labels, if any, followed by a second switch on the
computed integer value.

The second switch has the same code structure as the original string switch statement
except that the string case labels are replaced with positional integer constants starting at 0.

The first switch statement can be thought of as an inlined map from strings to their position in the case
label list. An alternate implementation would use an actual Map for this purpose, as done for enum switches.

With some additional effort, it would be possible to use a single switch statement on the hash code of the
argument, but care would need to be taken to preserve the proper control flow in the presence of hash
collisions and other complications, such as fallthroughs. Switch statements with one or two
alternatives could also be specially translated into if-then statements to omit the computation of the hash
code.

The generated code assumes that the hashing algorithm of String is the same in the compilation environment as
in the environment the code will run in. The string hashing algorithm in the SE JDK has been unchanged
since at least JDK 1.2. Since the algorithm has been specified since that release as well, it is very
unlikely to be changed in the future.

Different hashing algorithms, such as the length of the strings or a perfect hashing algorithm over the
particular set of case labels, could potentially be used instead of String.hashCode.

举一个具体的例子,如下:

class TestStringSwitch {
	public void test() {
		String fruit = "";
		switch (fruit) {
		case "banana":
		case "apple":
			System.out.println("banana or orange");
			break;
		case "orange":
			System.out.println("orange");
			break;
		default:
			System.out.println("default");
			break;
		}
	}
} 

翻译后的最终结果为:

    /*synthetic*/ final String s99$ = (fruit);
    /*synthetic*/ int tmp99$ = -1;
    switch (s99$.hashCode()) {
    case -1396355227:
        if (s99$.equals("banana")) tmp99$ = 0;
        break;

    case 93029210:
        if (s99$.equals("apple")) tmp99$ = 1;
        break;

    case -1008851410:
        if (s99$.equals("orange")) tmp99$ = 2;
        break;

    }
    switch (tmp99$) {
    case 0:
    case 1:
        System.out.println("banana or orange");
        break;

    case 2:
        System.out.println("orange");
        break;

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

    }

哈希函数在映射的时候可能存在冲突,多个字符串的哈希值可能是一样的,所以还要通过字符串比较来保证。

 

  

Javac语法糖之EnumSwitch的更多相关文章

  1. Javac语法糖之内部类

    在Javac中解语法糖主要是Lower类来完成,调用这个类的入口函数translateTopLevelClass即可.这个方法只是JavacCompiler类的desugar方法中进行了调用. 首先来 ...

  2. Javac语法糖之增强for循环

    加强的for循环有两种,遍历数组和实现了Iterable接口的容器.javac通过visitForeachLoop()方法来实现解语法糖,代码如下: /** Translate away the fo ...

  3. Javac语法糖之其它

    1.变长参数 class VarialbeArgumentsDemo { public static void doWork(int... a) {//可变参数 } public static voi ...

  4. Javac语法糖之TryCatchFinally

    https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3 Optionally replace a try s ...

  5. Javac语法糖之Enum类

    枚举类在Javac中是被当作类来看待的. An enum type is implicitly final unless it contains at least one enum constant ...

  6. Java中的10颗语法糖

    语法糖(Syntactic Sugar):也称糖衣语法,指在计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用.通常来说,使用语法糖能够增加程序的可读性,减少程序代码出错的 ...

  7. 转:【深入Java虚拟机】之六:Java语法糖

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/18011009 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家P ...

  8. 【转】剖析异步编程语法糖: async和await

    一.难以被接受的async 自从C#5.0,语法糖大家庭又加入了两位新成员: async和await. 然而从我知道这两个家伙之后的很长一段时间,我甚至都没搞明白应该怎么使用它们,这种全新的异步编程模 ...

  9. Java的语法糖

    1.前言 本文记录内容来自<深入理解Java虚拟机>的第十章早期(编译期)优化其中一节内容,其他的内容个人觉得暂时不需要过多关注,比如语法.词法分析,语义分析和字节码生成的过程等.主要关注 ...

随机推荐

  1. 对C++里面 的知识积累:

    unique()[去重函数] unique()是C++标准库函数里面的函数,其功能是去除相邻的重复元素(只保留一个),所以使用前需要对数组进行排序 上面的一个使用中已经给出该函数的一个使用方法,对于长 ...

  2. Java异常处理机制的秘密

    一.结论 这些结论你可能从未听说过,但其正确性是毋庸置疑的,不妨先看看: 1.catch中throw不一定能抛回到上一层,因为finally中的return会抑制这个throw 2.finally中t ...

  3. Miniprofiler在swagger、vue、angular中的使用

     本篇分为以下几个部分: 1.Swagger的简单应用 2.Miniprofier的后台配置 3.跨域配置 4.在angular中显示Miniprofier 5.在vue中显示Miniprofier ...

  4. Python3------装饰器详解

    装饰器 定义:本质是函数.(装饰其他函数)就是为其他函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 理解装饰器前提条件: 1.函数即"变量&qu ...

  5. web窗体ListView配置分页

    一.配置objectDataSource 1.选择业务逻辑层的类,再选择对应的分页方法 2.配置Select对应的方法,必须是一个带两个整型参数的方法,第一个参数表示要查看的第一条记录的前一条,第二个 ...

  6. ruby,gem,rails之间的关系

    Q:ruby,gem,rails之间的关系? 简单点说:Ruby是一种脚本语言,Gem是基于Ruby的一些开发工具包,Rails也算是一组Gem,专门用来做网站的.不同的Gem可能会依赖不同的Ruby ...

  7. List泛型集合对象排序

    本文的重点主要是解决:List<T>对象集合的排序功能. 一.List<T>.Sort 方法 () MSDN对这个无参Sort()方法的介绍:使用默认比较器对整个List< ...

  8. 【大数据之数据仓库】kudu性能测试报告分析

    本文由  网易云发布. 这篇博文主要的内容不是分析说明kudu的性能指标情况,而是分析为什么kudu的scan性能会这么龊!当初对外宣传可是加了各种 逆天黑科技的呀:列独立存储.bloom filte ...

  9. iOS App的加固保护原理

    本文由  网易云发布. 本文从攻防原理层面解析了iOS APP的安全策略.iOS以高安全性著称,但它并非金刚不坏之身.对于信息安全而言,止大风于青萍之末是上上策,杭研深入各个细节的研发工作,正是网易产 ...

  10. 知物由学 | AI时代,那些黑客正在如何打磨他们的“利器”?(一)

    本文由  网易云发布. “知物由学”是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道.“知物由学” ...