java7switch语法特性

 

switch 语句 基本每门计算机编程语言都有类似的语法结构,基本都是根据表达式的值选择要执行的语句块。而根据条件表达式的类型,不同编程语言所所提供的支持是不一样的。在java7以前,这个表达式只是支持整形以及与之兼容的类型(int,byte,short,char,当然还有后来特定支持的枚举类型),但是和这些基本类型所对应的封装类(Integer,Byte,Short,Character)也是不支持的。因此假如有其他的类型表达式,也就是必须的要添加额外的代码,来转换成相应的支持的类型,因此降低了代码的灵活性。在这儿,java主要是给提供switch语句支持的String类型。当然这些使得开发人员的开发变得也就是更简单了。

  • switch语句的基本用法

假如现在有这么一个场景,有某一个程序需要根据某人的性别来判断生成合适的称谓,比如:男性就称呼”xxx先生“,女士就称呼”xxx女士“,这儿判断的表达式类型就是String。

测试代码如下:

public class NameTest{


public String generate(String name,String gender)
    {    
    String s=null;
    switch(gender)//表达式类型为String,这儿的表达式不能够为null,否则这儿抛出NullPointerException.
        {
        case "男"://case后面一般跟的是常量(不能够为Null),这儿是String的字面值。
                s=name+"先生";
                break;
        case "女":
                s=name+"女生";
                break;
        }
    return s;
    }
}

值得注意的一点是 ,case子句中的值是不能重复的,字符串也是一样的。不过对于String,有一种特殊的地方,java中的代码支持Unicode转义字符。重复值的检查是在编译器对java源代码进行相关的词法分析转换后才进行的,这个词法转换也是包括Unicode转义字符。

比如下面的代码:

public class NameTest{


public String generate(String name,String gender)
    {    
    String s=null;
    switch(gender)
        {
        case "男":
                
                break;
        case "\u7537":
                break;//这儿的男和"\u7537"经过词法转换之后其实是一样的,也就是说这个代码不能够通过编译。
        }
    return s;
    }
}
  • 实现原理

实际上,java中得switch语句支持String表达式,是在编译器这个层次实现的,而在java虚拟机和字节代码这个层次上还是支持的int 和相应所兼容的。

其实编译器这个层次可以简单的理解成:java源代码中使用的是String,但是在编译过程中,会根据这个源代码的含义来进行简单的转换,将之转换成与int 和相应所兼容的类型(但是这个转换是根据不同的编译器的,也就说不通的编译器,这个转换方式不样的,并采用不同的优化策略)。for example,如果switch语句中只包含一个case语句,则可以简单的转换为if语句;如果包含两个,则可以转换成if-else遇见;包含多个case的话,那么就得要转换成java7支持的switch语句,不过这儿的String类型的的哈希值作为switch语句的表达式的值;

这儿使用了一个反编译(class文件->.java文件)工具JAD,将上面的代码经过编译之后生成了一个class文件,用JDA将之转换成源代码。如下:

public class NameTest{
    public String generate(String name,String gender){
        String s=null;
        String s1=gender;
        byte byte0=-1;
        switch(s1.hashCode){
            case 30007:
                if(s1.equals("\u7537"))
                    byte0=0;
                    break
            case 22899:
                if(s1.equals("\u5973"))
                    byte0=1;
                    break;
        } 
        switch(byte0){
            case 0:
                s=(new StringBuffer()).append(name).append("\u5148\u751F").toString;
                break;
            case 1:
                s=(new StringBuffer()).append(name).append("\u5937\u58EB").toString;
                break;
            default:
                s=name;
                break;
        }
        return s;
    }


}

从这个代码可以看的出,switch语句中的String 的引用转换成相应的哈希值,而case中的字面值也是被转换成相应的哈希值。通过这样的转换之后,java虚拟机仍然看到的只是int和相应兼容的。

注意:这里的String的比较要用equals这个方法,不能字符串的哈希值进行比较,因为hash函数在映射的时候可能会 发生冲突,造成多个字符串的哈希值可能相同。

  • switch中的枚举类型

就我个人而言,java7中的String这个类型为开发人提供了便利,但是容易造成误用,造成代码的维护性比较差。

在java5中提出了这种比较安全的枚举类型,就比如运用switch语句最常的就是在枚举的几个值之间进行选择,比如上面的男女选择,或者选择一个星期的某一天等,在java5之前的做法就是用整数来为这些枚举量进行编号。比如0表示男,1表示女。这样的做法其实弊端比较多的,比如不是类型很安全,没有 命名空间,可维护性比较差,不够直观等。再后来的发展中,出现了enum关键字,实现了其类型安全的机制。

java中的枚举类型最大的优势就是他是一个完整的类,其中定义了枚举值,方法和域(属性),以及能够实现各种的接口和继承抽象类,使得能够与java类进行很好的交互。在有多个枚举值时,我觉得优先考虑使用枚举这种类型比较好。

在java7之前,如果要枚举的zhi本身就是String的字面值,就只能够使用enum这种方法,但是在java7中就有了String表达式的支持,放弃了enum,虽然方便了,但是我们应该记住,这个维护比较麻烦,尤其是在程序之中经常出现了switch语句。而且程序之中经常出现字符串常量总是不好的习惯。

对此,个人认为,如果代码中出现了比较多的switch语句来枚举字符串,那么使用enum来代替比较好的一种办法。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值