第三章
3.1 引言
3.2 boolean数据类型
3.3 单分支if语句
Java 有几种类型的选择语句:单分支 if 语句、双分支if else语句、嵌套 if 语句、多分支 if else 语句、switch 语句和条件表达式
流程图是描述算法或者过程的图 ,处理操作显示在盒子中,棱形的盒子表示一个布尔类型的条件,矩形盒子代表语句
布尔表达式应该用括号括住。
if (i > 0) {
System.out.print("i is positive");
}
如果花括号内只有一条语句,则可以省略花括号。
if (i > 0)
System.out.print("i is positive");
3.4 双分支if-else语句
3.5 嵌套if 语句和多分支 if-else 语句
相比于嵌套if语句,多分支的if-else语句可以避免深度缩进,并使程序易于阅读
3.6 常见的错误和陷阱
常见错误1:对布尔值的冗余测试
//冗余
If (even == true)
System.out.print("it is even.");
//这种效果更好
If (even)
System.out.print("it is even.");
常见错误 2: 悬空 else 出现的歧义
在同一个块中,else 总是和离它最近的 if 子句匹配。这样,图 a 中的语句就等价于图 b 中的语句。
//错误的缩进
int i = 1, j = 2, k = 3;
if (i > j)
if (i > k)
System.out.println("A");
else
System.out.println("B");
//正确的缩进
int i = 1, j = 2, k = 3;
if (i > j)
if (i > k)
System.out.println("A");
else
System.out.println("B");
由于(i>j)为假,所以图 a 和图 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");
常见错误 3: 两个浮点数值的相等测试
通常,将Epsilon( ϵ \epsilon ϵ)设为 1 0 − 14 10^{-14} 10−14来比较两个double 类型的值,而设为 1 0 − 7 10^{-7} 10−7来比较两个 float 类型的值。
final double EPSILON = 1E-14;
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" );
常见陷阱 1: 简化布尔变量賦值
if (number % 2 == 0)
even = true;
else
even = false;
//这样写更好
boolean even = number % 2 ==0;
常见陷阱 2: 避免不同情形中的重复代码
if (inState) {
tuition - 5000;
System.out.println("The tuition is " + tuition);
}
else {
System.out.println("The tuition is " + tuition")
//这样写更好
if (instate) {
tuition = 5000;
}
else {
tuition = 15000;
}
System.out.println(''The tuirion is " + tuition);
3.7 产生随机数
可以使用Math.random()来产生一个[0.0 , 1.0)之间的随机double值
3.8 示例学习:计算BMI
3.9 示例学习: 计算税率
3.10 逻辑操作符
逻辑操作符!、&&、||、^可以用于产生复合布尔表达式。
p1 != p2 等同于 p1 ^ p2
从教学的角度看,表达式1 <= numberOfDaysInAMonth <= 31是正确的。但是,在Java 中它是错的,因为1 <= numberOfDaysInAMonth得到的是一个布尔值的结果,它是不能和31进行比较的,正确的写法应该是
(1 <= numberOfDaysInAMonth) && (numberOfDaysInAMonth <= 31)
德模佛定理
!(condition1 && condition2)
和
!condition1|| !condition2
是等价的
!(condition1|| condition2)
和
!condition1&&!condition2
是等价的。
可以简化为等价的表达式:
! (number % 2 == 0 && number % 3 == 0)
(number % 2 != 0 || number % 3 != 0)
另外一个例子
!(number == 2 || number == 3)
number != 2 && number != 3
在编程术语中,&和||被称为短路或者懒惰操作符,当前一种boolean值可以直接决定计算结果,就不再计算后面的boolean值
3.12 示例学习:彩票
3.13 switch语句
-
switch表达式必须能计算出一个char、byte、short,int或者String型值,并且必须总是要用括号括住。
-
value1, …, valueN必须与switch表达式的值具有相同的数据类型。注意: valuel, valueN 都是常量表达式,也就是说这里的表达式是不能包含变量的,不允许出现1+X。
-
当switch表达式的值与case语句的值相匹配时,执行从该case开始的语句,直到遇到一个 break语句或到达该 switch 语句的结束。
-
默认情况(default)是可选的,当没有一个给出的case与switch表达式匹配时,用来执行该操作。
-
关键字 break是可选的。break 语句会立即终止 switch 语句。不要忘记在需要的时候使用break语句。一旦匹配其中一个case,就从匹配的case 处开始执行,直到遇到 break 语句或到达 switch 语句的结束。这种现象称为落空行 为(fall-through behavior)。
3.14 条件表达式
如果布尔表达式的值为 true, 则条件表达式的结果为表达式 expression1; 否则,结果为表达式 expression2。
boolean-expression ? Expression1 : expression2;
(布尔表达式 ? 表达式1 : 表达式2)
假设希望将 num1 和 num2 中较大的数赋值给max, 可以利用条件表达式,只需编写一 条语句:
max = (num1 > num2) ? Num1 : num2;
如果num是偶数,下面的语句就显示信息 “num is even";否则显示
“num is odd”:
System.out.println((num % 2 == 0) ? "num is even" : "num is odd");
Java中唯一的三元操作符就是?:两个符号在条件表达式中同时出现
3.15 操作符的优先级和结合规则
如果优先级相同的操作符相邻,则结合规则(associativity) 决定它们的执行顺序。除了赋值操作符之外,所有的二元操作符都是左结合的(left associative)。
a - b + c -d 等价于 ((a - b) + c) - d
a = b+= c = 5 等价于 a = (b += (c = 5))
假设赋值前 a 、b 和 c 都是 1, 在计算表达式之后,a 变成 6,b变成 6, 而 c 变成 5。
3.16 调试
调试是在程序中找到和修改错误的过程
因为编译器可以明确指出错误的位置以及出错的原因,所以语法错误是很容易发现和纠正的。运行时错误也不难找,因为程序在异常终止时,错误的原因和位置都会显示在控制台上。然而,査找**逻辑错误(bug)**就很富有挑战性。
逻辑错误也称为臭虫(bug)。査找和改正错误的过程称为调试(debugging)。
调试的一般途径是采用各种方法逐步缩小程序中 bug 所在的范围。可以手工跟踪(hand trace) 程序 ( 即通过读程序找错误 ),也可以插入打印语句,显示变量的值或程序的执行流程。
以上方法适用于短小、简单的程序。对于庞大、复杂的程序,最有效的调试方法还是使用调试工具。
JDK包含了一个命令行调试器jdb,运行自身的一个 Java 解释器的拷贝。
一次执行一条语句
跟踪进入或者一步运行过一个方法
设置断点
显示变量
显示调用堆栈
修改变量