文章目录
前言
第二篇主要总结流程控制结构中的分支结构,先大体了解流程控制结构都有哪些,并对分支结构作了详细的总结和易错点的分析以及原理的一些学习分享。
一、三种流程结构
1、顺序结构
程序由上往下一次执行的结构
public class Demo01 {
public static void main(String[] args) {
System.out.println(1);
System.out.println(2);
System.out.println(3);
}
}
输出结果:
1
2
3
依次执行语句
2、分支结构
以顺序结构为基础,判断某一条件是否成立,根据条件的成立与否执行不同的代码块。
public class Demo02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入:");
int number = scanner.nextInt();
if (number>=10){
System.out.println("输入的数字大于等于10");
}else {
System.out.println("输入的数字小于10");
}
}
}
输入1,控制台输出:“输入的数字小于10”
输入11,控制台输出:“输入的数字大于等于10”
根据不同的判断结果来执行不同的代码块
3、循环结构
以顺序结构为基础,在限定条件下,重复执行代码块
public class Demo03 {
public static void main(String[] args) {
int i = 1;
while (i<=5){
System.out.println("输出第"+i+"次");
i++;
}
}
}
控制台输出结果:
输出第1次
输出第2次
输出第3次
输出第4次
输出第5次
在满足限定条件的情况下,重复执行代码块
二、分支结构(if、switch)
1、if语句
正如上面的例子,if语句就是通过()中的判断条件来执行不同的结果。
语法格式:
if(条件表达式){
代码块;
}
条件表达式:一个布尔表达式,通过此表达式得出布尔值,布尔值为真则执行代码块儿,为假则不执行直接跳过
代码块:一条或多条代码。
此处需要注意,在编码规范的角度不要去省略{},即使只有一条语句,这样方便阅读代码,增加代码可读性
除了if还有和它搭配的另一个关键字else
使用if和else配合就可以在条件表达式成立和不成立两种情况下执行不同的代码块。
if(){
代码块;
}else{
代码块;
}
这两个关键字也是顾名思义,if(如果)、else(其他),但是只通过这两个关键字在一些复杂逻辑下就会出现多层嵌套的情况,写出的代码一言难尽,例子:
public class Demo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入number的值:");
int number = scanner.nextInt();
if (number > 100) {
System.out.println("大于100");
} else {
if (number > 90) {
System.out.println("大于90小于等于100");
} else {
if (number > 80) {
System.out.println("大于80小于等于90");
} else {
if (number > 70) {
System.out.println("大于70小于等于80");
} else {
if (number > 60) {
System.out.println("大于60小于等于70");
} else {
if (number > 50) {
System.out.println("大于50小于等于60");
} else {
if (number > 40) {
System.out.println("大于40小于等于50");
} else {
if (number > 30) {
System.out.println("大于30小于等于40");
} else {
if (number > 20) {
System.out.println("大于20小于等于30");
} else {
if (number > 10) {
System.out.println("大于10小于等于20");
} else {
System.out.println("小于等于10");
}
}
}
}
}
}
}
}
}
}
}
}
在逐渐加深的缩进中我们也会增加代码的阅读难度,并且增加了代码量,所以遇到这种情况的时候,就需要使用else if的多重结构
上述代码等价于
public class Demo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入number的值:");
int number = scanner.nextInt();
if (number > 100) {
System.out.println("大于100");
} else if (number > 90) {
System.out.println("大于90小于等于100");
} else if (number > 80) {
System.out.println("大于80小于等于90");
} else if (number > 70) {
System.out.println("大于70小于等于80");
} else if (number > 60) {
System.out.println("大于60小于等于70");
} else if (number > 50) {
System.out.println("大于50小于等于60");
} else if (number > 40) {
System.out.println("大于40小于等于50");
} else if (number > 30) {
System.out.println("大于30小于等于40");
} else if (number > 20) {
System.out.println("大于20小于等于30");
} else if (number > 10) {
System.out.println("大于10小于等于20");
} else {
System.out.println("小于等于10");
}
}
}
使用else if后的代码不再有复杂的深度缩进,变得一目了然,每个条件的关系也很容易就能看出来。
这也是if语句的第三种语法格式:
if(){
代码块;
}else if(){
代码块;
}else{
代码块;
}
2、if语句易错点
(1)不加“{}”易出现的歧义
if (number > 10)
if (number > 20)
System.out.print("执行结果A");
else
System.out.print("执行结果B");
这种情况的else与它最接近的if为一组,也就是等价于
if (number > 10){
if (number > 20)
System.out.print("执行结果A");
else
System.out.print("执行结果B");
}
若是要让else与第一个if为一组,则需要使用{}
if (number > 10){
if (number > 20)
System.out.print("执行结果A");
}
else
System.out.print("执行结果B");
所以在平时的使用中最好加上{},方便阅读,规避一些细节上的错误
(2)浮点数的比较使用==出现的错误
这个在上一篇博客中有说明,浮点数类型使用==进行值的比较很容易出现错误,因为浮点数类型的计算精度,会出现精度丢失的错误。
3、switch语句
switch语句语法规则
switch (表达式){
case 值1:
执行代码;
break;
case 值2:
执行代码;
break;
default:
执行代码;
break;
}
表达式:取值类型可以是byte、short、int、char、JDK5以后可以是枚举类型、JDK7以后可以是字符串类型
case:后面跟的值是与表达式比较的值,当两者相等则会执行代码片段
break:结束代码块儿的关键字,也就是说执行了break后就会跳出switch语句的代码块,除了最后一个case或者default以外不可省略
default:当表达式和所有的值都不匹配的时候就会进入default执行代码片段
注意事项:
- 当表达式为字符串类型的时候,case后面的值要用双引号,当表达式为char类型的时候,case后面的值用单引号
- 处理异常情况最好是使用default语句来进行
例子
public class Demo05 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("选择您要购买的饮品:");
System.out.println("1.可乐");
System.out.println("2.矿泉水");
String choose = scanner.next();
switch (choose){
case "1":
System.out.println("可乐3元,购买成功");
break;
case "2":
System.out.println("矿泉水2元,购买成功");
break;
default:
System.out.println("选项错误");
break;
}
}
}
4、了解switch语句的原理和if效率的比较
参考文章:
(1)switch的原理理解
在学习了switch后一直对switch的原理感到好奇,为什么可以通过改变switch(表达式)括号内的表达式来进入到不同的case选项中执行代码,由此在大佬文章的帮助下,了解到了关于switch语句的底层原理,虽然理解并不透彻,但通过学习和自己的理解对switch语句总算有了一些认知。同时switch的这种处理方式很像稀疏数组,有兴趣也可以了解
首先根据case后值的关系的不同分为两种:
- 当case后跟随的值紧凑时:比如1、2、3、4,这种情况下,使用tableswitch
- 当case后跟随的值不紧凑时:比如1、1000、10000,使用lookupswitch
根据观察,大概tableswitch采用一种key-value的存储方式
例如:有case后的值:1、3、5
那么就会被编译成可能是:
{
1:87;
2:153;
3:98;
4:153;
5:109;
default:153;
}(举例并非实际值)
当执行switch的时候,jvm就会识别到tableswitch指令,用switch括号内的值与这个表进行比较,在1-5之间,就会与这项的指定位置进行内容替换,不在此范围就会直接执行default的内容,同时这种操作会补全没有连续的部分与default的值相同
由上可以看出这种方式在效率上的优势,但是同时也有它的不足,如果不连续的地方全都需要补充,遇到大数字的时候就会很占用资源。
于是第二种情况,lookupswitch解决了不紧凑的情况。
例如:
有case后的值为:10、1000、10000
{
10 : 101
1000:156
10000:178
default:80
}(举例并非实际值)
这种方式也是通过key-value的方式存储,但是虚拟机会对key值进行排序,来提高搜索效率,这种方式必须依次检查switch中的键匹配,遇到相等会执行,遇到超过最大值的直接进入default,没找到一样执行default。
(2)效率比较
综上所述,switch的原理,是通过key-value的方式来对数据进行存储查找,这种方式相比于if语句每次都需要逻辑判断的方式效率会高上不少。
5、switch语句的易错点
先看代码:
public class Demo08 {
public static void main(String[] args) {
int i = 1;
switch (i){
default:
System.out.println("default");
case 1:
System.out.println(1);
case 2:
System.out.println(2);
break;
case 3:
System.out.println(3);
case 4:
System.out.println(4);
}
}
}
结果:
1
2
由此可见,switch case语句只有遇到break才会结束语句的执行,否则会继续执行,并且之后的语句有没有break和本次执行并无关系
public class Demo08 {
public static void main(String[] args) {
int i = 2;
switch (i){
default:
System.out.println("default");
case 1:
System.out.println(1);
case 2:
System.out.println(2);
break;
case 3:
System.out.println(3);
case 4:
System.out.println(4);
}
}
}
将i的值改成2后,结果为:
2
由此可见,当switch括号内的值与case后的值匹配上后才会进入到语句之中
public class Demo08 {
public static void main(String[] args) {
int i = 8;
switch (i){
default:
System.out.println("default");
case 1:
System.out.println(1);
case 2:
System.out.println(2);
break;
case 3:
System.out.println(3);
case 4:
System.out.println(4);
}
}
将i的值改为8进入default,结果为:
default
1
2
由此可见,default一样需要break才能结束,结合switch的原理,可见default其本质和case后的值的本质相同,都是匹配key-value的值,没有匹配到的时候就等于是匹配了default的值
public class Demo08 {
public static void main(String[] args) {
int i = 8;
switch (i){
case 1:
System.out.println(1);
default:
System.out.println("default");
case 2:
System.out.println(2);
break;
case 3:
System.out.println(3);
case 4:
System.out.println(4);
}
}
将default的位置改变后,结果为:
default
2
可见,输入不匹配的值的时候,default就会成为入口,它在哪就在哪进入
总结上面的错误得出结论:
- switch语句中必须配合break才能结束,否则就会按照顺序结构持续执行代码,无论是case还是default都是一样
- 无论是case还是default,都是switch语句的入口,当能够匹配上case后的值的时候就会进入这个值后的语句执行,若没有匹配上任何的case,就会进入default的入口执行语句。
- default的功能和它在哪个位置没有关系
总结
本篇文章到此结束,总结分析过后发现这些细枝末节的知识点任然需要多加巩固和练习才能融会贯通,对switch语句原理的学习也是掌握到很多关键的知识点。