以下内容为博主阅读对应书籍或资料(分栏名告知)总结的笔记,由部分书内原句、部分佐证、部分博主自身理解组成,有出错处万望告知,不胜感谢。
本类文章主为巩固博主自身学习,顺带与同行互通有无,若有侵权望告知!
程序可以基于条件决定执行哪些语句
1.boolean数据类型
- boolean数据类型声明一个具有值 true 或者 false 的变量
- 布尔(boolean)表达式是计算结果为布尔值 true 或者 false 的表达式
- Java提供六种关系(比较)操作符,用于两个值的比较:
小于 “<” 等同于数学符号 “<” ,如示例(radius 值为 5):radius < 0 ,结果为 false
大于 “>” 等同于数学符号 “>” ,如示例(radius 值为 5):radius > 0 ,结果为 true
等于 “==” 等同于数学符号 “=” ,如示例(radius 值为 5):radius = 0 ,结果为 false
小于等于 “<=” 等同于数学符号 “≤” ,如示例(radius 值为 5):radius <= 0 ,结果为 false
大于等于 “>=” 等同于数学符号 “≥” ,如示例(radius 值为 5):radius >= 0 ,结果为 true
不等于 “!=” 等同于数学符号 “≠” ,如示例(radius 值为 5):radius != 0 ,结果为 true
- 关系操作符中的相等是 两个等号 “==”,单个等号 “=” 是赋值表达式!
- 保存布尔值的变量称为布尔变量,boolean数据类型用于声明布尔型变量
- true 和 false 都是字面值,类似于 10 这样的数字一样。它们被当做保留字一样不能用作程序中的标识符
- 数字数据类型与布尔数据类型的转化:
boolean b = true; int i = (int)b; System.out.print(i); // 1 i = 0; b = (boolean)i; System.out.print(b); // false
即在数字与布尔数据类型转换时,1 视作 true,0 视作 false
2.if语句
- if 语句是一个构造,允许程序确定执行的可选路径
- Java中的选择语句类型有(罗列后逐个阐述):
单分支 if 语句、
双分支 if 语句、
嵌套 if 语句、
多分支 if-else 语句、
switch 语句 和
条件语句
2.1.单分支 if 语句
语法:
if(布尔表达式) {
// 语句(组);
}
当 if 语句后的布尔表达式结果为 true 时执行 行内块语句,为 false 时则跳过该 if 语句后的行内块语句
当花括号内只有一条语句时可以省略花括号
但是这种写法会增加后续阅读和修改代码的难度,因此 不建议使用
2.2.双分支 if 语句
语法:
if(布尔表达式) {
// 布尔表达式结果为 true 时执行的语句(组);
} else {
// 布尔表达式结果为 false 时执行的语句(组);
}
语法已经能够很好地解释双分支 if 语句的执行方式,不作赘述
2.3.嵌套 if 语句 和 多分支 if-else 语句
这两个语句的效果类似但不相同,放一块便于比较区分
- 语法:
嵌套 if 语句:
if(i > k) {
// 当 i 大于 k 时执行此处及以下的代码
if(j > k) {
// 当 j 大于 k 时还会执行此处的代码
// 还可以继续嵌套更多的 if 语句:
if(l > k) {
// ...
}
}
}
多分支 if-else 语句:
if(i > 90) {
// 当 i 大于 90 时执行此处及以下的代码
} else if(i > 75) {
// 当 i 大于 75 时还会执行此处的代码
// 还可以继续嵌套更多的 else if 语句:
} else if(i > 60) {
// ...
}
嵌套 if 语句(便于阅读简称嵌套语句) 和 多分支 if-else 语句(便于阅读简称多分支语句)同样都是对条件进行多重判断,用以处理 符合不同条件 的不同情况数据
而在实际使用中,嵌套语句更偏向于判断不同类型需求的条件、多分支语句更偏向于判断相同类型需求的条件
例如根据学生的成绩进行排挡处理,由于区分条件只有一种(成绩),因此使用多分支语句更佳
而例如社交网站,需要根据性别、年龄、籍贯、兴趣爱好等不同方面的各个条件进行划分,此时使用嵌套语句来进行判断效果则更好
2.4.switch 语句
语法:
switch(switch表达式) {
case 值1: 语句(组)1;
break;
case 值2:语句(组)2;
break;
...
case 值N:语句(组)Nv;
break;
default:默认情况下(一般为条件都不符合时)执行的语句(组)
}
而 break 并不要求出现在每个 case(情况)后的执行语句中,它的效果是提前结束运行之后的语句……直到符合下一个条件(不常见)或相当于结束该 switch 语句
若 switch 语句中漏写了应当存在的 break 语句可能会导致条件判断后的执行结果异常(比如任意条件满足就会一直执行完之后的所有结果)
以下例子为便于理解 break 用和不用的情况:将3、4、5月视为春季 switch(moon) { case 3: case 4: case 5: System.out.println(moon +"月是春季"); // 由于对3、4、5月份的季节判定相同,因此不区分处理,即不论是满足哪个条件最终都是得到“春季”这个结论 // 以下几个季节同理 break; case 6: case 7: case 8: System.out.println(moon +"月是夏季"); break; case 9: case 10: case 11: System.out.println(moon +"月是秋季"); break; case 12: case 1: case 2: System.out.println(moon +"月是冬季"); break; default : // 当用户输入值不满足所有情况——即不是1~12时: System.out.println("请输入正确的月份"); }
switch 语句 与 多分支语句类似,而多分支语句更多的是针对条件为 范围值 时使用,switch 语句啧更多的偏向于条件为可能的 具体值 时使用
例如:
关于季节的判断:if(moon >= 3 && moon <= 5) { System.out.println(moon + "月是春季"); } else if(moon >= 6 && moon <= 8) { System.out.println(moon + "月是夏季"); } else if(moon >= 9 && moon <= 11) { System.out.println(moon + "月是秋季"); } else if(moon == 12 || moon <= 2 && moon >=1) { System.out.println(moon + "月是冬季"); } else { System.out.println("请输入正确的月份"); }
此处附上一则代码简化写法(稍微)
// print不换行,println换行
System.out.print(moon +"月是");
switch(moon) {
case 3:
case 4:
case 5:
System.out.print("春");
// 由于对3、4、5月份的季节判定相同,因此不区分处理,即不论是满足哪个条件最终都是得到“春季”这个结论
// 以下几个季节同理
break;
case 6:
case 7:
case 8:
System.out.print("夏");
break;
case 9:
case 10:
case 11:
System.out.print("秋");
break;
case 12:
case 1:
case 2:
System.out.print("冬");
break;
default :
// 当用户输入值不满足所有情况——即不是1~12时:
System.out.println("请输入正确的月份");
}
System.out.println("季");
// 不过在这里这种写法反而有可能导致输出值异常,比如 moon 值为 13 时:
/* displays:
13月是
请输入正确的月份季
**/
// 因此这块代码主要是提供一种编程思路,当重复代码过多时可考虑这种写法简化
相较而言:看起来 else if 的方式更为简洁(行数少),而事实上编写起来的难度较之于 switch 的方式更为繁复
由于值确定且数量较少(12种),switch 方式显得更为直观
而当条件的可能性增多或比如值为浮点型数据时,情况数量就会大大增加甚至是无穷的,即在实际使用时 else if 这种方式的判断语法使用频率会更高
2.5.条件语句(即 三元运算符)
语法:
// 将 num1 和 num2 中较大的数赋值给 max
max = (num1 > num2) ? num1 : num2;
// “?” 前的语句判断为 true 时赋值 “:” 前的数据,为 false 时赋值 “:” 后的数据
// 可以理解为:
if(num1 > num2) {
max = num1;
} else {
max = num2;
}
三元运算符 的有效利用可以明显简化代码的繁复性(多行代码一行搞定),许多语言都有使用三元运算符
3.逻辑操作符
逻辑操作符 ! 、&& 、|| 、 ^ 可以用于产生复合布尔表达式:
- !:逻辑非,改变原本的判断结构 -> true 变 false , false 变 true
- && :逻辑与,其两边的布尔表达式判断结果都为 true 总的才为 true
- || :逻辑或,其两边的布尔表达式判断结果只要有一个为 true 则为 true ,否则 false
- ^ :逻辑异或,效果等同于 != 即不等于,两边判断结果不同时为 true ,否则 false
逻辑非和逻辑与有个共同点:
即左边的布尔表达式结果有时会跳过后面的语句
&& 左边为 false 时提前结束,返回 false
|| 左边为 true 时提前结束,返回 true
4.注意事项、常见错误异常及陷阱
- if 语句的布尔表达式需要 写在括号中
- if 行不能出现== 分号 ==
- 对布尔值的冗余测试
以下代码示例:
if(even == true)
System.out.println("It is even.");
// 此处 if 中的 even 即冗余测试,括号内会默认判定布尔值,无需主动增加 == true 的判断
// 不算错误,但没有必要,也会降低可读性(与大众习惯不符)
// 这样即可:
if(even)
System.out.println("It is even.");
- 悬空 else 出现歧义:
int i = 1, j = 2, k = 3;
if(i > j)
if(i > k)
System.out.println("A");
else
System.out.println("B");
// 你以为这个 else 是跟第一个 if 匹配?实际上在程序看来它是这样的:
int i = 1, j = 2, k = 3;
if(i > j)
if(i > k)
System.out.println("A");
else // 就近原则进行匹配,而 else 的缩进并不会影响程序的识别!
System.out.println("B");
// 而如果一定要 else 与第一个 if 匹配:
int i = 1, j = 2, k = 3;
if(i > j) {
if(i > k)
System.out.println("A");
} else
System.out.println("B");
// 而事实上,用这种语法习惯写 if 语句属于吃力不讨好的行为,最好的方式还是每个 if 语句都加上花括号
int i = 1, j = 2, k = 3;
if(i > j) {
if(i > k) {
System.out.println("A");
}
} else {
System.out.println("B");
}
- 两个浮点数值的相等测试:
double x = 1.0 - 0.1 - 0.1 - 0.1 - 0.1 -0.1;
System.out.println(x == 0.5); // 以为是 true ,而实际上是 false
// 因为在此处 x 的值并不精确等于 0.5,而是 0.5000000000000001
// 可以使用近似比较(误差极小的情况下)
final double EPSILON = 1E-14; // 比较 double 数据时使用 1E-14,比较 float 数据时使用 1E-7(精度原因)
double x = 1.0 - 0.1 - 0.1 - 0.1 - 0.1 -0.1;
if (Math.abs(x - 0.5) < EPSILON) {
System.out.println(x + "is approximately 0.5");
}
- 简化布尔变量赋值:
if(number % 2 == 0) {
even = true;
} else {
even = false;
}
// 这样相当于通过 if 判断后再赋值,可以这样写来简化:
boolean even
= number % 2 == 0;
- 避免不同情形中的重复代码:
if(inState) {
tuition = 5000;
System.out.println("The tuition is " + tuition);
} else {
tuition = 15000;
System.out.println("The tuition is " + tuition);
}
// 这种重复代码的情况在比较 switch 和 else if 时就有提到,这样来简化:
if(inState) {
tuition = 5000;
} else {
tuition = 15000;
}
System.out.println("The tuition is " + tuition);
5.调试
调试是在程序中找到和修改错误的过程
- 首先回顾错误类型:
语法错误:编译器可以明确指出错误的位置以及错误的原因,因此最容易解决;
运行时错误:程序异常终止时会在控制台显示出错误的位置及原因,稍微麻烦但也算很难解决;
逻辑错误:被称为臭虫(即 bug),最难找出出错位置和原因,常常需要耗费大量精力时间 - 而这里所说的调试,主要就是指的调制逻辑错误,查找和改正错误的过程被称为调试(debugging)