Java程序设计精讲二 第三章 流程控制语句1
1 Java程序结构
一个Java程序可以由一个或多个.java文件组成,这些文件称为源文件。每个源文件中含有一个或多个类或接口。一个源文件中如果有多个类,则最多只能有一个是public类型的类,且该源文件的名字即为这个公有类的名字,且大小写也要一致。其他非public的类的个数不限。 一个Java程序的结构包含以下内容:
- package语句:包语句,每个文件最多只有一个,且必须放在文件开始的地方。
- import语句:引入语句,可以没有,也可以有多个,如果有import语句的话,必须放在所有类定义的前面。
- 具有public权限的类定义:每个文件中最多有一个。
- 类定义:每个文件中包含的非public权限的类定义的个数没有限制。
- 接口定义:每个文件中包含的接口定义个数没有限制。
1.1. Java包的概念
- 包是类的容器,包的设计人员利用包来划分名字空间,以避免类名冲突。程序员也可以定义自己的包,可以使用package语句来命名。 包语句的格式为:
package pkg1[.pkg2[.pkg3...]];
- 程序中如果有package语句,该语句一定是源文件中的第一条非注释语句,它的前面只能有注释或空行。另外,一个文件中最多只能有一条package语句。
- 包的名字有层次关系,各层之间以点分隔。包层次必须与Java开发系统的文件系统结构相同。通常包名中全部用小写字母。一个包要放在指定目录下,通常用CLASSPATH指定搜寻包的路径。类名就是文件名,包名就是文件夹名,即目录名。
1.2. 引入语句
引入语句的格式如下:
import pkg1[.pkg2[.pkg3...].(类名|*);
其中,格式语句中如果指明具体的类名,则表示引入的是这个具体的类;要引入包中的所有类时,可以使用通配符*
。1 2
import java.util.*; //引入包中的所有类 import java.util.ArrayList; //只引入了包中的ArrayList类
源文件中,可以同时出现package语句和import语句,但要特别注意它们的次序。package语句在import语句之前,且最多只能有一个package语句。
实际上,程序中并不一定要有引入语句。当引用某个类的类与被引用的类存储在同一个物理目录下时,可以直接使用被引用的类。
2 流程控制语句
2.1. 赋值语句
2.1.1. 概念
赋值语句:表达式可以当作一个值赋给某个变量,这样的语句称为赋值语句。
表达式语句:有的表达式也可单独当作语句,这样的语句称为表达式语句。
2.1.2. 语句与表达式的异同点
- 有的表达式可以当作语句,但并不是所有的语句都是表达式;
- 每个表达式都会得到一个值,即表达式的计算结果。虽然语句也会有一个值,但这个值并不是语句的计算结果,而是执行结果。
2.2. 分支语句
2.2.1. if语句
if 语句是单重选择,最多只有两个分支。if语句的基本格式是
1
2
3
4
5
if(条件表达式)
语句1;
[else
语句2;
]
注意:
- if关键字之后的条件表达式必须得到一个逻辑值。
- if语句中的else子句是可选的,语句1和语句2可以是任意的语句,且只能是一条语句。如果想写多条语句时,需要使用大括号
{ }
把多条语句组成一个块。 - 语句1和语句2还可以是if语句,这样的if语句称为嵌套的if语句。使用嵌套的if语句可以实现多重选择,也就是可以有多个分支。嵌套语句中, if的个数可能多于else的个数,故匹配时,else子句属于逻辑上离它最近的if语句。如果想改变else的匹配关系,可以使用
{ }
改变语句结构。
2.2.2. switch语句
当需要进行多个条件的判断时,可以使用嵌套的if语句来实现。为了方便地实现多重分支,提供了switch语句。switch语句的语法格式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch(表达式){
case c1:
语句组1;
break; // break语句可选
case c2:
语句组2;
break; // break语句可选
...
case ck:
语句组k;
break; // break语句可选
[default:
语句组;
break; // break语句可选
]
}
注意:
- 这里,表达式的计算结果必须是int型或char型,即是int型赋值相容的。当用byte型或short型时,要进行提升。Java规定switch语句不允许使用浮点型或long型表达式。c1,c2…,ck是int型或字符型常量。default子句是可选的,并且,最后一个break语句完全可以不写。
- 如果没有相匹配的ci,则执行default之后的语句。不论执行哪个分支,程序流都会顺序执行下去,直到遇到break语句跳到switch之后的语句。
2.3. 循环语句
2.3.1. for语句
语法格式:
1
2
for(初始语句;条件表达式;迭代语句)
循环体语句;
注意: for语句括号内的3个部分都是可选的,条件表达式为空时,默认规定为恒真。
语义: 先执行初始语句,判断条件表达式的值,当条件表达式为真时,执行循环体语句,再执行迭代语句,然后去判别条件表达式的值。这个过程一直进行下去,直到条件表达式的值为假时,循环结束,转到for之后的语句继续执行。
2.3.2. while语句
for语句中常常用循环控制变量显式控制循环的执行次数。当程序中不能明确地指明循环的执行次数时,可以仅用条件表达式来决定循环的执行与否。这样的循环可用while语句来实现。 语法格式:
1
2
while(条件表达式)
循环体语句;
注意: 和if语句一样,while语句中的条件表达式亦不能用数值来代替。
语义: 计算条件表达式的值,当值为真时,重复执行循环体语句,直到条件表达式为假时结束。如果第一次检查时条件表达式为假,则循环体语句一次也不执行。如果条件表达式始终为真,则循环不会终止。
2.3.3. do-while语句
语法格式:
1
2
3
do
语句;
while(条件表达式);
语义: 首先执行循环体语句,然后判定条件表达式的值,当值为真时,重复执行循环体语句,直到表达式的值为假时结束循环。不论条件表达式的值是真是假,do循环中的循环体都至少执行一次。
2.4. 跳转语句
2.4.1. 标号
标号可以放在任意语句之前,通常与for、while或do语句配合使用。
语法格式:
1
标号:语句;
2.4.2. break语句
break语句可用于3类语句中:
在switch语句中。
在for、while及do等循环语句中。
在语句块中。在switch语句及循环语句中,break的语义是跳过本块中余下的所有语句,转到块尾,执行其后的语句。
break语句的第三种使用方法是在块中和标号配合使用,其语法格式为:
1
break 标号;
其语义是跳出标号所标记的语句块,继续执行后面的语句。这种形式的break语句多用于嵌套块中,控制从内层块跳到外层块之后。
2.4.3. continue语句
在循环语句中,continue语句可以立即结束当次循环,开始执下一次循环,当然执行前要先判断循环条件是否满足。 continue语句也可以和标号一起使用,其语法格式为:
1
continue 标号;
它立即结束标号标记的那重循环的当次执行,开始下一次循环。这种形式的语句多用于多重循环中。
3 简单的输入/输出
3.1. Scanner类
Scanner类属于
java.util
包。它提供了许多方法,可用来方便地读入不同类型的输入值。比如从键盘输入、从文件中输入等。创建一个Scanner类对象,它读入键盘输入:
1
Scanner scan = new Scanner(System.in);
注意:
- Scanner类的构造方法接收一个参数,这个参数代表了输入源。System.in对象代表标准输入流,默认是指键盘。
- Scanner对象用空白(空格、水平制表符及回车换行符)作为输入的分隔元素。这些空白称为分隔符。也可以指定用其他的符号作为分隔符。
Scanner类的方法
next()
方法读入下一个输入对象,将它作为字符串返回。空格分割。nextLine()
方法读入当前行的所有输入,直到行尾,然后作为字符串返回。
3.2. NumberFormat类和DecimalFormat类
Java提供的格式化输出功能:
NumberFormat类提供对数值进行格式化操作的一般功能。不能使用new运算符实例化一个NumberFormat对象,只能直接使用类名调用一个特殊的静态方法来得到一个对象。 NumberFormat类中常用的方法如下:
- getInstance():返回当前默认语言环境的默认数值格式。
- getCurrencylnstance():返回当前默认语言环境的通用格式。
- getNumberInstance():返回当前默认语言环境的通用数值格式。
- getPercentInstance():返回当前默认语言环境的百分比格式。
- setMaximumFractionDigits(int):设置数值的小数部分允许的最大位数。
- setMaximumIntegerDigits(int):设置数值的整数部分允许的最大位数。
- setMinimumFractionDigits(int):设置数值的小数部分允许的最小位数。
- setMinimumIntegerDigits(int):设置数值的整数部分允许的最小位数。
DecimalFormat类属于Java标准类库,定义在java.text包中。 使用new运算符来实例化对象。它的构造方法要带一个String类型的参数,这个参数表示格式化处理模式。然后可以使用format()方法对一个具体的值进行格式化。之后,还可以调用applyPattern()方法来改变对象要使用的模式。 程序中,可以自行设置传给DecimalFormat构造方法的模式,它由一个字符串来定义。不同的符号表示不同的格式信息。
1 2 3 4
static void decimalFormat() { DecimalFormat format = new DecimalFormat("0.##"); // 最少保留两位小数 System.out.println(format.format(123456789.1)); //123456789.1 }
4 处理异常
4.1. 异常及其处理机制
Java提供了异常处理机制,预定义了Exception类。 在一个方法的运行过程中,如果发生了异常,称程序产生了一个异常事件,相应地生成异常对象。生成异常对象并把它提交给运行时系统的这一过程称为抛出 (Throw)一个异常。Java运行时系统从生成对象的代码块开始进行回溯,沿方法的调用栈逐层回溯,寻找相应的处理代码,直到找到包含相应异常处理的方法为止,并把异常对象交给该方法处理。这一过程称为捕获(Catch)。当发现并响应异常时,就是处理(Handle)了异常。 简而言之,发现错误的代码可以“抛出”一个异常,程序员可以“捕获”该异常,如果可能则“处理”它,然后恢复程序的执行。
4.2. 异常分类
Java语言在所有的预设包中都定义了异常类和错误类。Exception类是所有异常类的父类,Error类是所有错误类的父类,这两个类同时又是Throwable类的子类。
受检异常,必须被处理。 受检异常(Checked Exception )是程序执行期间发生的严重的后果。发生的原因可能是用户给程序提供了一个错误的文件名。 Java类库中的下列类表示受检异常:
ClassNotFoundException 、FileNotFoundException、IOException、NoSuchMethodException及WriteAbortedException
。- 运行时异常,不需要处理。 运行时异常(Runtime Exception)通常是程序中逻辑错误的结果。例如,数组下标越界导致ArrayIndexOutOfBounds异常。被0除导致ArithmeticException异常。 Java类库中的下列类表示运行时异常:
ArithmeticException 、ArraylndexOutOfBoundsException、ClassCastException、EmptyStackException、lllegalArgumentException、IllegalStateException、IndexOutOfBoundsException、NoSuchElementException、NullPointerException和UnsupportedOperationException
。 - 错误,不需要处理。 错误(Error)是标准类Error或其后代类的一个对象,Error是Throwable的后代。一般地,错误是指发生了不正确的情况,如内存溢出。这些情况都比较严重,一般不处理它们。
- 很多异常类都在包java.lang中,所以不需要引入。但有些异常类在另外的包中,它们必须要引入。例如,当在程序中使用类IOException时,必须要使用引入语句:
import java.io.IOException;
4.3. 异常处理
- 当发生异常时,程序通常会中断执行,并输出一条信息。对所发生的异常进行的处理就是异常处理。异常处理的重要性在于,程序不但能发现异常,还要能捕获异常。
- 对于可能引发受检异常的方法,有两种选择:在方法内处理异常,或是告诉方法的调用者来处理。
- 处理异常的代码 含有两段:第一段try块含有可能抛出异常的语句。第二段含有一个或多个catch块。每个catch块含有捕获及处理某种类型异常的代码。
4.4. 公共异常
- ArithmeticException:整数除法中,如果除数为0,则发生该类异常。
- NullPointerException:如果一个对象还没有实例化,那么访问该对象或调用它的方法将导致该类异常。
- NegativeArraySizeException:创建数组时,如果元素个数是负数,则会引发该类异常。
- ArrayIndexOutOfBoundsException:Java把数组看作是对象,并用length变量记录数组的大小。如果数组下标越界,则将导致该类异常。
4.5. 抛出异常
程序员处理异常有两种方法:
使用try块和catch块,捕获到所发生的异常类,并进行相应的处理。
程序员不在当前方法内处理异常,而是把异常抛出到调用方法中。
- 方法内执行throw语句时会抛出一个异常,一般的形式如下。
1 2 3 4
throw exception_object; //throw语句创建了一个异常对象exception_object,如: throw new IOException(); //这个语句创建类IOException的一个新对象并抛出它。抛出异常时也应该尽可能地具体
- 在方法头中用Java保留字throws来声明这个方法可能抛出的异常;在方法体中用保留字throw实际抛出一个异常。这两个保留字不要弄混。