第五章 流程控制、异常与断言
5.1 if和switch语句
考试目标2.1 编写实现if或switch语句的代码,并辨别这些语句的合法变元类型。
if和switch语句通常被称作判决语句。在程序中使用判决语句时,是在要求程序计算一个给定的表达式,以判断要采取哪个操作。
5.1.1 if-else 分支
int a = 10;
if(a>20){
//doStuff
}else if(a<20){
//doStuff
}else{
//doStuff
}
if 语句的合法表达式
if语句的唯一合法表达式是布尔表达式。换句话说,只能是可以被解析为布尔值或布尔变量的表达式。
注意布尔赋值(=),它可能被错认为不二相等性(==)测试
public class Test{
public static void main(String[] args){
boolean b = true;
if(b=true){
System.out.println("b="+b);
}
}
}
结果:b=true
public class Test{
public static void main(String[] args){
boolean b = true;
if(b=false){
System.out.println("b="+b);
}
}
}
结果:(什么都没有)
5.1.2 switch 语句
switch (x) {
case 1:
// doStuff
break;
case 2:
// doStuff
break;
case 3:
// doStuff
break;
case 4:
// doStuff
break;
default:
// doStuff
}
switch 和 case 的合法表达式
switch(expression){
case constant1: code block
case constant2: code block
default: code block
}
switch的表达式必须能求值成char、byte、short、int或者枚举。这意味着如果没有使用枚举,则只有能够被自动提升为int的变量和值才是可接受的。
case后面的常量必须是字面值或final变量,或者是常量表达式,包括枚举。不能在case中包含非final变量或一个取值范围。
switch 块内的中断和直落
case只是这个switch块的入口,如果没有碰到break,它会一直执行下去,直到遇到break,或者switch的尾部。
默认 case
default :{}
default case 不一定总要置于switch的末尾。
5.2 循环和迭代器
考试目标2.2 编写代码,实现循环和迭代器的所有形式,包括使用for、增强型for循环(for-each)、do、while、标签、break和continue,并解释在循环执行期间和执行之后循环计数器变量所具有的值。
5.2.1 使用while循环
while (expression) {
//do stuff
}
//expression应该是一个测试条件,不应将声明放在这里。满足条件执行循环体一次。
5.2.2 使用do循环
do{
//do stuff
}while(expression);
//先执行一次循环体,完成后判断expression的结果,为true则再次执行一次循环体,false则跳出循环
5.2.3 使用for循环
旧式的for循环称为“基本for循环”,新式的称之为“增强型for循环”(for-each循环)
基本for循环
for循环声明包括3个主要部分:变量的声明和初始化,布尔表达式(条件测试),迭代表达式
基本for循环:声明和初始化
for语句的第一部分允许在for关键字之后的圆括号内声明并初始化0个、1个或多个同类型的变量。变量的作用域随着for循环的结束而结束。
for(int x=10,y>3;y>3;y++){}
基本for循环:条件(布尔)表达式
只能有一个测试表达式,不能使用逗号分隔的多个测试,但for语句中的另外两个部分可以有多个成分。
for(int x=0;(((x<10)&&(y-->2))|x==3);x++){}
基本for循环:迭代表达式
for循环体每次执行之后,都会执行迭代表达式。
除了强制退出之外,for循环中最后做的两件事总是:先计算迭代表达式,然后计算条件表达式。
强制退出包括:break、return、System.exit()方法或者异常。
基本for循环:for循环问题
for(;i>10;){}就像一个while(i>10){}
增强型for循环(用于数组)
for语句的两个部分是:
声明(declaration)。新声明的块变量,其类型与正在访问的数组元素的类型兼容。
表达式(expression)。它必须计算为想要遍历的数组。
List<Object> aa = new ArrayList<Object>();
for(Object a:aa){
// do stuff
}
增强型for循环假定:除非提前退出循环,否则总会遍历数组的每一个元素。
5.2.4 使用break和continue
break终止整个循环,continue终止当前的迭代。
5.2.5 无标签的语句
“5.2.4”中说的就是无标签的情况
5.2.6 带标签的语句
标签要作为所标识的循环的前缀,并在标签名后加“:”。如下:
boolean isTrue = true;
outer:
for(int i = 0;i<5;i++){
while(isTrue){
System.out.println("Hello");
break outer;
}
System.out.println("Outer loop.");
}
System.out.println("Good-Bye");
//结果:
//Hello
//Good-Bye
//可见,如果无标签,break只跳出while,但实际直接跳出了被标记为outer的for循环。
5.3 处理异常
考试目标2.4 编写使用异常和异常处理子句(try、catch、finally)的代码,并声明抛出异常的方法和重写方法。
考试目标2.5 了解代码段内特定点所产生的异常的后果。注意,异常可以是运行时异常、检验异常或错误。
异常语句就是告诉JVM“这些代码可能会出问题,你来监视他,我会告诉你万一出问题了该怎么办”。
异常有两种形式:检验异常和非检验异常。
检验异常包括Exception的所有子类型,但不包括扩展RuntimeException的类。
检验异常遵守处理或声明它的规则,任何可能抛出检验异常的方法(包括调用能够抛出检验异常方法的方法),都必须使用throws关键字声明异常,或者用适当的try/catch处理异常。
Error或RuntimeException的子类型是非检验异常,因此,编译器不强迫要求处理或声明规则。你可以随意声明或处理它们,编译器对此并不关心。
5.3.1 使用try和catch捕获异常
5.3.2 使用finally
finally块,只要不是JVM关闭这种情况,则finally块总会运行。
try{
//do stuff
}catch(Exception ex){
//catch exception
}finally{}
5.3.3 传播未捕获的异常
当我们不打算在这里处理异常,可以将异常throw,由下面来处理它。
5.3.4 定义异常
异常是一个改变正常程序流程的事件。
当抛出一个异常时,某个特定的Exception子类型的对象被实例化,并作为catch子句的变元传递到异常处理程序。
5.3.5 异常层次
Throwable的两个子类型:Exception 和 Error。
应用程序不能从Error恢复,这就谈不上处理。异常表示不是由程序设计错误导致发生的错误,而是由于某个资源不可用,或者正确执行所需的其他某个条件不满足所造成的。
5.3.6 处理整个异常类层次
在单个catch子句内可以捕获多种类型的异常。通常我们的异常处理应该是有针对性的,不分情况直接catch Exception的做法是不可取的,最好捕获明确的异常子类型,有针对的处理,编写catch处理代码。
5.3.7 异常匹配
最具体的异常处理程序必须总是放在更一般的异常处理程序的上面。
5.3.8 异常声明与公共接口
每个方法必须通过提供catch子句处理所有检验异常,或者将每个未处理的检验异常列为一个抛出的异常。
5.3.9 重抛同一个异常
在catch子句中可以写 “throw xxx;”这样的语句来重抛同一个异常。
5.4 常见异常和错误
考试目标2.6 识别将导致以下任何一种异常或错误被抛出的情况:ArrayIndexOutOfBoundsException、ClassCastException、IllegalArgumentException、IllegalStateException、NullPointerException、NumberFormatException、AssertionError、ExceptionInInitializerError、StackOverflowError或者NoClassDefFoundError。理解其中哪些是由虚拟机抛出的,并识别应该以编程方式抛出另外一些异常和错误的情况。
异常来自于那里?
- JVM异常。这些异常或错误由JVM抛出,具有排他性或者最具逻辑性。
- 程序异常。这些异常由应用程序和/或API程序员显式地抛出。
JVM抛出的异常
以编程方式抛出的异常
考试中的异常和错误小结
常见异常的描述和来源表:
异常 |
描述 |
通常由谁抛出 |
ArrayIndexOutOfBoundsException |
试图用一个无效索引值(可能为负或者超出了数组的大小)访问数组时抛出 |
JVM |
ClassCastException |
试图将一个引用变量强制转换为一个不能通过IS-A测试的类型时抛出 |
JVM |
IllegalArgumentException |
当方法接收到的变元格式不同于该方法需要的格式时抛出 |
以编程方式 |
IllegalStateException |
当环境的状态与正在尝试的操作不匹配时抛出(例如,使用一台已关闭的扫描仪) |
以编程方式 |
NullPointerException |
试图访问带有一个当前值为null的引用变量的对象时抛出 |
JVM |
NumberFormatException |
一个用于将String转换为数值的方法接收到一个不能转换的String时抛出 |
以编程方式 |
AssertionError |
当一条语句的布尔测试返回false时抛出 |
以编程方式 |
ExceptionInInitializerError |
试图初始化静态变量或静态初始化块时抛出 |
JVM |
StackOverflowError |
当方法递归层次过深时,通常会抛出这个异常(每次调用都会添加到栈中) |
JVM |
NoClassDefFoundError |
由于命令行错误、类路径问题,或者丢失了.class文件,使JVM找不到需要的类时抛出 |
JVM |
5.5 使用断言机制
考试目标2.3 编写使用断言的代码,并区分断言的正确使用和错误使用。
5.5.1 断言(Assertion)概述
当测试和调试时,你想验证你的假设,但是又不希望在开发完成时去除print语句、运行时异常处理程序或if/else测试。但是将它们保留在程序中至少对向能有所影响。
这时就可以使用断言。它可以在实际部署时被系统自动清除。
断言的工作方式:它总是断定某件事情为true,如果不是,则立刻抛出AssertionError异常,告诉你这里跟你想的不一样。
断言的两种形式:
//非常简单(really simple)
assert(y>x);
//简单(simple)
assert(y>x):"y is "+y+" x is "+ x;
//这个字符串会被添加到栈踪迹中。
断言表达式规则:
public class TestAssert {
void noReturn(){}
int aReturn(){return 1;}
void go(){
int x = 2;
boolean b = true;
//合法的
assert(x==1);
assert(b);
assert true;
assert(x==1):x; //第二种表达式“:”后面可以返回的是任何值
assert(x==1):aReturn();
assert(x==1):new TestAssert();
//非法的
// assert(x=1);
// assert(x);
// assert 0;
// assert(x==1):;
// assert(x==1):noReturn();
// assert(x==1):TestAssert test;
}
public static void main(String[] args){
TestAssert obj = new TestAssert();
obj.go();
}
}
5.5.2 启用断言
标识符与关键字
可以将assert用作关键字或者标识符,但是不能同时将它用作这两者。
使用java和javac的版本6
编译带有断言的代码
javac -source 1.4 JavaObjcet.java
带断言运行
默认情况下 断言是禁止的。
运行时启用断言
java -ea com.geeksanonymous.TestClass
java -enableassertions com.geeksanonymous.TestClass
运行时禁用断言
java -da com.geeksanonymous.TestClass
java -disableassertions com.geeksanonymous.TestClass
有选择地启用和禁用
java -ea:com.foo.Bar 在类com.foo.Bar中启用断言
java -ea -da:com.foo.Bar 在除了类com.foo.Bar的其他类中启用断言
java -ea:com.foo... 在包com.foo以及它的任何子类包中启用断言
java -ea -dsa 通常启动断言,但在系统类中禁止
5.5.3 适当地使用断言
不要使用断言验证公共方法的变元
可以使用断言验证私有方法的变元
不要使用断言验证命令行变元
即使在公共方法内,也可以使用断言检查从不会发生的情况
不要使用可能产生副作用的断言表达式
分享到:
相关推荐
1. **题目与答案**:这部分可能包含了一系列针对SCJP考试的实践题目,以及对应的参考答案。考生可以通过做这些题目来检查自己的理解程度,了解考试可能涉及的知识点,从而进行有针对性的复习。 2. **PPT**(演示...
2. **学习笔记**: "scjp_amay's notes for 1.4.doc"可能是一位名叫Amay的学习者针对Java 1.4版本的SCJP考试整理的笔记,这个版本可能包含对当时Java语言特性的详细解析,例如原始类型、字符串常量池、异常处理机制等...
1. "SCJP 6.0認證教戰手冊考題1-100.pdf":这部分涵盖了100道考题,主要针对Java的基础知识,如语法、数据类型、流程控制、异常处理、面向对象编程等。考生可以通过这些题目熟悉基本概念和编程技巧。 2. "SCJP 6.0...
1. **Java语言基础**:SCJP认证的基础部分涵盖了Java语法的各个方面,包括数据类型、变量、运算符、流程控制语句(如if-else、switch、for、while)、数组、方法、字符串处理等。理解这些基本概念对于编写有效的Java...
这个压缩包"SCJP_Guide.rar_scjp"包含了备考SCJP的关键资料,特别是"SCJP_Guide.pdf",这很可能是官方的学习指南或模拟试题集,对于准备考试的人来说是极其宝贵的资源。 SCJP考试主要涵盖以下几个方面的知识点: 1...
通过这些题目,我们可以学习到Java中的类型转换规则、方法的重载和覆盖、异常处理机制以及静态变量的特性,这些都是Java编程基础的重要组成部分,对于通过SCJP认证考试以及日常编程工作都非常有帮助。在实际编程中,...
根据给定文件的信息,我们可以深入探讨SCJP 310-055考试中的异常处理和断言相关知识点。此部分题库主要聚焦于Java语言中的异常处理机制以及如何正确地使用断言来确保代码质量。 ### 异常处理 在Java中,异常处理是...
SCJP(Sun Certified Programmer for the Java Platform)是Oracle公司(原Sun Microsystems)为Java程序员提供的一项认证考试,现称为Oracle Certified Associate, Java SE 8 Programmer。这个认证主要针对那些希望...
这个认证旨在验证开发者对于Java编程语言的基础知识和理解能力,包括语法、数据类型、控制结构、异常处理、类与对象、多线程、输入/输出以及集合框架等方面的知识。SCJP证书对于那些希望在Java开发领域提升职业竞争...
1. **Java基础知识**:这部分涵盖了Java语言的基础语法,包括变量、数据类型、运算符、流程控制(如if语句、for循环、while循环)、方法定义与调用、数组等。 2. **面向对象编程**:Java的核心特性是面向对象,因此...
本书主要内容包括:声明和访问控制、面向对象、赋值和初始化、运算符、流程控制、异常和断言、I/O、格式化和解析、泛型、集合、内部类、线程和Java开发。书中在介绍考试要点时针对每个考试目标,使用了大量的插图...
1. **Java基础**:涵盖Java语法、数据类型、流程控制、类与对象、封装、继承、多态等核心概念。 2. **异常处理**:理解Java的异常体系,学习如何使用try-catch-finally语句块处理程序中的错误。 3. **集合框架**:...
### SCJP复习笔记知识点解析 #### 一、八进制与十六进制表示法 - **八进制**: 在Java中,八进制数是以数字`0`开头的数(而不是字母`o`)。例如,`010`表示的是八进制数,其对应的十进制值为`8`。 - **十六进制**: ...
Scjp笔记 - 帝国程序开发
### SCJP知识点总结 #### 常量声明与修饰符使用 - **常量声明**:使用`public static final`来声明一...以上内容根据提供的SCJP笔记进行了详细解释和扩展,旨在帮助读者更好地理解Java编程语言的核心概念和技术要点。