-
switch语句
2019-02-17 19:36:16switch语句从字面上讲,可以称为开关语句,当然理解上不要以为就只有开和关,可以想象它是一个多路开关。它是一种多分支结构。 switch语句的语法形式为: switch(整型表达式) { case 常量表达式1:语句1 case ...1. 语句结构
语法形式
switch语句从字面上讲,可以称为开关语句,当然理解上不要以为就只有开和关,可以想象它是一个多路开关。它是一种多分支结构。
switch语句的语法形式为:
switch(整型表达式) { case 常量表达式1:语句1 case 常量表达式2:语句2 //…… case 常量表达式n-1:语句n-1 default:语句n }
解读整型表达式
switch后面的小括号是一个整型表达式,这与if不同。if条件表现的是相互对立的两种状态,而对于多分支结构的switch,是用多个整数值表现多种选择。if条件的对立性总是相对于0而言,所以只要某种数据类型的表达式能够表示0值,便可以充当if语句的条件,但是switch中的表达式的值需要对应到不同的处理入口,其相当于入口编号,所以限制以用整型数表示是明智的。
例如,下面的代码错误地用浮点类型作switch的表达式,因而会引起编译错误:
float f= 4.0; switch (f) { //错误 //…… }
处理入口
“case常量表达式:”即处理入口(也称其为“标号”),常量表达式相当于入口编号,入口编号是不能重复的,所以每一个case的常量表达式的值必须互不相同。
例如,下面的代码是某个switch语句的局部,其case处理入口出现相同常量值,导致了编译错误:
case 'A' :cout<<"this is A\n"; case 'B' : cout<<"this is 65\n"; //错误,A等于ASCII码的65
处理入口编号不能重复,但可以颠倒。也就是说,入口编号的顺序不重要。各个case(包括default)的出现次序可任意。例如:
swtich(a) { case 3: b=1; break; default: b=2; break; //正确 case 1: b=3; break; }
default处理入口:如果switch后面的整型表达式不能匹配任何一个预定的处理入口,那么若有default处理入口,就转入该入口,否则就退出switch语句,什么也不做。
2. switch嵌套
switch语句可以嵌套,也就是在switch语句中的入口处理语句中又包含了switch语句。case与default标号是与包含它的最小的switch相联系的。例如:
int i,j; //…… switch(i) { case 1 :// case 2 : switch(j) { //嵌套switch case 1: case 2: default: } case 3: }
switch(j)中的标号(入口编号)虽然与外面的switch(i)中的标号相同,但编译器不会混淆。
需要switch嵌套是基于switch中的入口语句可以是语句集合,而语句集合是可能需要开关语句作进一步编程处理的。
3. 用好break
全程顺序性
在if语句中,if与else属下各自描述的语句是彼此独立的。但是在switch语句中,每个case只是标定处理入口,各个入口的语句并不排他。因此,switch语句中的全部处理入口描述的语句构成了一个顺序执行的动作序列。例如,下列代码描述一个五级计分的程序:
switch(grade){ case 'A': cout<<"Excellent\n"; case 'B': cout<<"Very Good\n"; case 'C': cout<<"Good\n"; case 'D': cout<<"Satisfactory\n"; case 'E': cout<<"Minimally Acceptable\n"; default : cout<<"Error\n"; }
当变量grade取'D'值时,将输出:
Satisfactory
Minimally Acceptable
Error
而不是所想象的单一的Satisfactory字串。
break的排他性
为了让switch中处理入口的语句具有入口独立性,从而有更多的描述灵活性,语言中专为switch语句配备了break语句。在switch语句中遇上break便意味着终止switch语句的执行,这就自然地构成了各个入口语句的互斥。改写上述代码,在每个入口处理的最后填上break语句,便得到:
switch(grade){ case 'A': cout<<"Excellent\n";break; case 'B': cout<<"Very Good\n";break; case 'C': cout<<"Good\n";break; case 'D': cout<<"Satisfactory\n";break; case 'E': cout<<"Minimally Acceptable\n";break; default : cout<<"Error\n"; }
这时候,当变量grade取'D'时,将只输出对应的成绩描述字串:
Satisfactory
switch语句中的最后一条语句的下一句便是出口了,面对的是switch语句终止后的下一条语句,所以就没有必要再用break特地退出了。
放弃使用的效果
break语句是在switch语句中人为添加的,而不是默认的,这就多了一些编程操作而显得“笨拙”。一些评论家一次而攻击switch语句“太土”。但正由于加不加是可选的,给switch一些编程的灵活性。例如,频繁输入一个整数n以决定输出n个相同字串“Hello.”便可以有一种用switch语句的更好选择:
//方法1 for (int n; cin>>n;)//反复输入整数n { for(int i=1; i<=n; i=i+1)//循环控制输出n个字串(1≤n≤3) cout<<"Hello." cout<<"\n"; } //方法2 for(int n; cin>>n;) { switch(n){ case 3: cout<<"Hello."//都没有用break case 2: cout<<"Hello." case 1: cout<<"Hello." } cout<<"\n"; }
按这两种方法,则输入:
2 1 3 0 3
都能得到结果:
Hello.Hello.
Hello.
Hello.Hello.Hello.
Hello.Hello.Hello.
方法1在循环语句中嵌套使用了1~n的for循环语句,以决定输出语句执行的次数。不管怎么说,针对每次输入的整数,都要做n次条件判断。
方法2在循环语句中使用了开关语句,它通过直接转向执行,完成n次字串输出。
显然在上述代码中,循环控制结构所付出的代价相对多分支转向结构要大,若数据量很大,则会带来明显的性能差别。
由于n值很小,使用多分支语句时,通过安排处理的入口编号而使前后语句得到共享,语句简化且易懂。
选择使用的效果
break在switch语句中,对每个case分支都是可选的,也就是说,有些可以有,有些可以没有。因为有了这样的特性,编程变得更灵活。例如:
switch(ch){ case'-': b=-b;//无break case'+': a=a+b;break; case'*': a=a*b;break; case'/': a=a/b; }
首先要明白,在C++中,并不是只有整型数才可以做加减的。代码中a、b实体如果是大对象,做负号操作可能远比减法操作的代价小,减法操作可能比加法操作还要耗费精力,或者根本没有该数据类型的减法操作。因此,做减法不如预先做反向操作,再做加法划算。
break注解
break是一个关键字,该关键字独立构成一条语句,其功能是在switch、for、while、do-while语句中,跳出结构而转向执行吓一条语句。或者说break语句强行终止上述语句的执行。对于if语句,其if-else结构中的语句块本身就是排他性的,所以没有必要用break去干预。
-
技术大佬:我去,你写的 switch 语句也太老土了吧
2020-03-01 09:02:53但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!” 来看看小王写的代码吧,看完不要骂我装逼啊。 private static String createPlayer...昨天早上通过远程的方式 review 了两名新来同事的代码,大部分代码都写得很漂亮,严谨的同时注释也很到位,这令我非常满意。但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!”
来看看小王写的代码吧,看完不要骂我装逼啊。
private static String createPlayer(PlayerTypes playerType) { switch (playerType) { case TENNIS: return "网球运动员费德勒"; case FOOTBALL: return "足球运动员C罗"; case BASKETBALL: return "篮球运动员詹姆斯"; case UNKNOWN: throw new IllegalArgumentException("未知"); default: throw new IllegalArgumentException( "运动员类型: " + playerType); } }
看完上述代码后,你是不是会发出这样的感慨——“代码写得很好,没有任何问题啊!”是不是觉得我在无事生非,错怪了小王!但此时我要送上《了不起的盖茨比》中的一句话:
我年纪还轻,阅历不深的时候,我父亲教导过我一句话,我至今还念念不忘。 “每逢你想要批评任何人的时候, ”他对我说,“你就记住,这个世界上所有的人,并不是个个都有过你拥有的那些优越条件。”
哈哈,这句话不光是让你看的,也是给我看的。是时候冷静下来谈谈上述 switch 语句的老土问题了。
看到上图了吧,当不小心删掉 default 语句后,编译器就会报错,提示:“没有返回语句”,为了解决这个问题,我们可以新建一个 player 变量作为返回结果,就像下面这样:
private static String createPlayer(PlayerTypes playerType) { String player = null; switch (playerType) { case TENNIS: player = "网球运动员费德勒"; break; case FOOTBALL: player = "足球运动员C罗"; break; case BASKETBALL: player = "篮球运动员詹姆斯"; break; case UNKNOWN: throw new IllegalArgumentException("未知"); } return player; }
当添加了 player 变量后,case 语句中就需要添加上 break 关键字;另外在 switch 语句结束后,返回 player。这时候,编译器并不会提示任何错误,说明 default 语句在这种情况下是可以省略的。
从 JDK 12 开始(本例使用的是 JDK 13),switch 语句升级了,不仅可以像传统的 switch 语句那样作为条件的判断,还可以直接作为一个返回结果。来对小王的代码进行改造,如下所示:
private static String createPlayer(PlayerTypes playerType) { return switch (playerType) { case TENNIS -> "网球运动员费德勒"; case FOOTBALL -> "足球运动员C罗"; case BASKETBALL -> "篮球运动员詹姆斯"; case UNKNOWN -> throw new IllegalArgumentException("未知"); }; }
够 fashion 吧?不仅 switch 关键字之前加了 return 关键字,case 中还见到了 Lambda 表达式的影子,中划线和箭头替代了冒号,意味着箭头右侧的代码只管执行无须 break。
并且,default 语句变成了可选项,可有可无,不信?你也动手试试。
新的 switch 语句足够的智能化,除了有上述的 3 个优势,还可以对枚举类型的条件进行校验。假如在 PlayerTypes 中增加了新的类型 PINGPANG(乒乓球):
public enum PlayerTypes { TENNIS, FOOTBALL, BASKETBALL, PINGPANG, UNKNOWN }
此时编译器会发出以下警告:
意思就是 switch 中的 case 条件没有完全覆盖枚举中可能存在的值。好吧,那就把 PINGPANG 的条件加上吧。来看一下完整的代码:
public class OldSwitchDemo { public enum PlayerTypes { TENNIS, FOOTBALL, BASKETBALL, PINGPANG, UNKNOWN } public static void main(String[] args) { System.out.println(createPlayer(PlayerTypes.BASKETBALL)); } private static String createPlayer(PlayerTypes playerType) { return switch (playerType) { case TENNIS -> "网球运动员费德勒"; case FOOTBALL -> "足球运动员C罗"; case BASKETBALL -> "篮球运动员詹姆斯"; case PINGPANG -> "乒乓球运动员马龙"; case UNKNOWN -> throw new IllegalArgumentException("未知"); }; } }
switch 语句变成了强大的 switch 表达式,美滋滋啊!那假如一个运动员既会打篮球又会打乒乓球呢?
private static String createPlayer(PlayerTypes playerType) { return switch (playerType) { case TENNIS -> "网球运动员费德勒"; case FOOTBALL -> "足球运动员C罗"; case BASKETBALL,PINGPANG -> "牛逼运动员沉默王二"; case UNKNOWN -> throw new IllegalArgumentException("未知"); }; }
就像上述代码那样,使用英文逗号“,”把条件分割开就行了,666 啊!
不服气?switch 表达式还有更厉害的,
->
右侧还可以是{}
括起来的代码块,就像 Lambda 表达式那样。private static String createPlayer(PlayerTypes playerType) { return switch (playerType) { case TENNIS -> { System.out.println("网球"); yield "网球运动员费德勒"; } case FOOTBALL -> { System.out.println("足球"); yield "足球运动员C罗"; } case BASKETBALL -> { System.out.println("篮球"); yield "篮球运动员詹姆斯"; } case PINGPANG -> { System.out.println("乒乓球"); yield "乒乓球运动员马龙"; } case UNKNOWN -> throw new IllegalArgumentException("未知"); }; }
细心的同学会发现一个之前素未谋面的关键字
yield
,它和传统的 return、break 有什么区别呢?先来看官方的解释:
A yield statement transfers control by causing an enclosing switch expression to produce a specified value.
意思就是说 yield 语句通过使一个封闭的 switch 表达式产生一个指定值来转移控制权。为了进一步地了解
yield
关键字,我们可以反编译一下字节码:private static String createPlayer(NewSwitchDemo3.PlayerTypes playerType) { String var10000; switch(playerType) { case TENNIS: System.out.println("网球"); var10000 = "网球运动员费德勒"; break; case FOOTBALL: System.out.println("足球"); var10000 = "足球运动员C罗"; break; case BASKETBALL: System.out.println("篮球"); var10000 = "篮球运动员詹姆斯"; break; case PINGPANG: System.out.println("乒乓球"); var10000 = "乒乓球运动员马龙"; break; case UNKNOWN: throw new IllegalArgumentException("未知"); default: throw new IncompatibleClassChangeError(); } return var10000; }
编译器在生成字节码的时候对
yield
关键字做了自动化转义,转成了传统的 break 语句。这下清楚了吧?但是,话又说出来,那些看似 fashion 的代码也不过是把部分秀技的工作交给了编译器,还可能存在对旧版本不兼容、对队友不友好的问题——代码土点就土点呗,没准是最实用的。
“不好意思,我为昨天早上的嚣张向你道歉。。。。。。”我向小王发送了一条信息。
好了,我亲爱的读者朋友,以上就是本文的全部内容了,希望能够博得你的欢心。
最后,一定会有不少读者想要问我怎么学习 Java 的,那我干脆就把我看过的优质书籍贡献出来:
1)入门版:《Head First Java》、《Java 核心技术卷》
2)进阶版:《Java编程思想》、《Effective Java》、《Java网络编程》、《代码整洁之道》
3)大牛版:《Java并发编程》、《深入理解Java虚拟机》、《Java性能权威指南》、《重构》、《算法》
就先介绍这么多,希望对那些不知道看什么书的同学有所帮助。
对了,我介绍的这些书籍,已经顺便帮你整理好了,你可以在我的原创微信公众号『沉默王二』回复『书籍』获取哦
有收获?希望老铁们来个三连击,给更多的同学看到这篇文章
-
switch 语句
2020-11-19 23:01:59switch 语句 switch 语句的使用场景,与前面学习的 if - else if - else 语句一致。但是从代码角度来看,switch 语句比 if - else if - else 语句更为优美,但是又有自身的限制,在判断时,没有 if - else if - else...switch 语句
switch 语句的使用场景,与前面学习的 if - else if - else 语句一致。但是从代码角度来看,switch 语句比 if - else if - else 语句更为优美,但是又有自身的限制,在判断时,没有 if - else if - else 语句那么灵活。
switch 语句,先是判断一个变量与一系列值中的某个值是否相等,每个值对应一个分支,如果相等,则进入这个分支。
语法
switch 语句的语法格式如下:
switch(expression){ case value : 语句1 break; //可选 case value : 语句2 break; //可选 // 你可以有任意数量的case语句 default : //可选 语句3 }
switch 语句有如下规则:
1.switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE7 开始,switch 还支持字符串 String 类型,但是使用 String 类型时,case 标签必须为字符串常量或字面量;
2.switch 语句可以拥有多个 case 语句,每个 case 后面跟一个要比较的值和冒号;
3.case 语句中 value 的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量;
4.当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句;
5.当遇到 break 语句时,switch 语句终止,继续执行 switch 语句后面的语句。case 语句不一定要包含 break 语句,如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句;
6.switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。当 case 语句的值和所有变量值都不相等时,执行 default 分支。default 分支不需要 break 语句。
注意:switch 语句执行时,一定会先进行匹配。如果匹配成功,则返回当前 case 的值,再根据是否有 break,判断是否继续进行匹配判断。
案例:
public static void main(String args[]) { char grade = 'B'; switch (grade) { case 'A': System.out.println("优秀"); break; case 'B': System.out.println("良好"); break; case 'C': System.out.println("中等"); break; case 'D': System.out.println("及格"); break; case 'F': System.out.println("你需要再努力努力"); break; default: System.out.println("未知等级"); } System.out.println("你的等级是 " + grade); }
执行结果:
良好 你的等级是 B
代码说明:变量 grade 的值为 B ,进入 case B 的分支,打印“良好”,然后遇见了 break 语句,结束 switch 语句。继续执行 switch 后的语句,最后打印“你的等级是 B”。
-
Switch语句
2020-03-26 22:17:27相对于 if 语句而言,switch 语句可以更方便地应用于多个分支的控制流程。C89 指明,一个 switch 语句最少可以支持 257 个 case 语句,而 C99 则要求至少支持 1023 个 case 语句。然而,在实际开发环境中,为了程序...switch
相对于 if 语句而言,switch 语句可以更方便地应用于多个分支的控制流程。C89 指明,一个 switch 语句最少可以支持 257 个 case 语句,而 C99 则要求至少支持 1023 个 case 语句。然而,在实际开发环境中,为了程序的可读性与执行效率,应该尽量减少 switch 语句中的 case 语句。
除此之外,switch 语句与 if 语句不同的是,switch 语句只能够测试是否相等,因此,case 语句后面只能是整型或字符型的常量或常量表达式;而在 if 语句中还能够测试关系与逻辑表达式。
不要忘记在 case 语句的结尾添加 break 语句
在 switch 语句中,每个 case 语句的结尾不要忘记添加 break 语句,否则将导致多个分支重叠。当然,除非有意使多个分支重叠,这样可以免去 break 语句。下面我们来看一个实际示例。#include <stdio.h> void print_week(unsigned int day); void print_week(unsigned int day) { switch(day) { case 1: printf("Monday\n"); break; case 2: printf("Tuesday\n"); break; case 3: printf("Wednesday\n"); break; case 4: printf("Thursday\n"); break; case 5: printf("Friday\n"); break; case 6: printf("Saturday\n"); break; case 7: printf("Sunday\n"); break; default: printf("error\n"); break; } } int main (void) { print_week(3); return 0;
不要忘记在 switch 语句的结尾添加 default 语句
在 switch 语句中,default 语句主要用于检查默认情况,或者处理错误情况,如果在 switch 语句中去掉 default 语句,那么 switch 语句将失去对默认情况与错误情况的处理能力。所以,奉劝大家不要偷懒,老老实实把每一种情况都用 case 语句来完成,而把真正对默认情况的处理交给 default 语句来完成。即使程序真的不需要 default 处理,也应该保留此语句:
不要为了使用 case 语句而刻意构造一个变量
在实际编程应用中,switch 中的 case 语句应该只用于处理简单的、容易分类的数据。如果数据并不简单,却为了使用 case 语句而刻意构造一个变量,那么这种变量很容易令我们得不偿失。因此应该严格避免这种变量,并使用 if/else 结构来处理这类程序,如下面的示例代码所示:
尽量将长的 switch 语句转换为嵌套的 switch 语句
有时候,当一个 switch 语句中包括很多个 case 语句时,为了减少比较的次数,可以把这类长 switch 语句转为嵌套 switch 语句,即把发生频率高的 case 语句放在一个 switch 语句中,作为嵌套 switch 语句的最外层;把发生频率相对低的 case 语句放在另一个 switch 语句中,放置于嵌套 switch 语句的内层。
-
21年新消息队列RabbitMQ视频教程AMQP教程
-
单片机完全学习课程全五季套餐
-
MFC开发简单聊天程序
-
量化高频交易系统tick数据采集
-
北邮c++课件期末试题
-
第3章 入门程序、常量、变量
-
google_play_services_5077000_r18.zip
-
【数据分析-随到随学】互联网行业业务指标及行业数
-
编程题(三)
-
I2C地址修改.rar
-
性能测试面面观
-
latex 各级标题公式
-
ksyl
-
2021-01-23
-
History对象
-
flutter插件调用APP页面、使用原生aar,framework库
-
2021-01-23
-
搜索
-
Master of Typing - mac上的打字练习神器
-
spring-mybatis-spring-1.2.2_src.zip