-
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语句
2016-10-07 12:39:07switch作为选择语句,实际编程中,最易...1、switch语句称为情况选择语句,又称开关语句。JDK1.7之前的switch语句限定对整形数据进行判断。 switch(表达式){ case 常量值1: 代码块1; break; case 常量值2:switch作为选择语句,实际编程中,最易出错的就是 “贯穿”现象。下面对switch做一些介绍:
1、switch语句称为情况选择语句,又称开关语句。JDK1.7之前的switch语句限定对整形数据进行判断。
switch(表达式){
case 常量值1:
代码块1;
break;
case 常量值2:
代码块2;
break;
case 常量值3:
代码块3;
break;
...........default:
以上常量值均不是时,执行本代码。
}
2、Java Switch语句的“贯穿”现象
import java.util.Scanner; public class switch1 { public static void main(String[] args) { // TODO Auto-generated method stub int score=4; switch(score){ case 5: score++; case 4: score++;//执行 case 3: score++;//执行 case 2: score++;//执行 case 1: score++;//执行 case 0: score++;//执行 default: System.out.println(score);//输出:9 } } }
3、键盘输入字符串并进行判断import java.util.Scanner; public class switch1 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner=new Scanner(System.in); System.out.println("输入分数等级:"); char grade=scanner.next().charAt(0);//获取字符串中的字符 switch(grade){ case '优': System.out.println(5); break; case '良': System.out.println(4); break; case '中': System.out.println(3); break; case '差': System.out.println(2); break; default: System.out.println("输入的等级错误"); } } }
4、switch显示指定月的天数
import java.util.Scanner; public class switch1 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner=new Scanner(System.in); System.out.println("请输入月份:"); int month=scanner.nextInt(); switch(month){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: System.out.println("31天"); break; case 2: System.out.println("28天"); break; case 4: case 6: case 9: case 11: System.out.println("30天"); break; default: System.out.println("输入的月份错误"); } } }
-
java switch语句_JAVA switch语句
2021-03-07 10:24:52流程控制语句switchswitch语句解构(重要)A:switch语句解构a:switch只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码。* b:格式如下:swtich(表达式){case 常量1 :要执行的语句;break;case 常量2 :要执行...