首页 Java程序设计精讲二 第三章 流程控制语句
文章
取消

Java程序设计精讲二 第三章 流程控制语句

Java程序设计精讲二 第三章 流程控制语句1

1 Java程序结构

一个Java程序可以由一个或多个.java文件组成,这些文件称为源文件。每个源文件中含有一个或多个类或接口。一个源文件中如果有多个类,则最多只能有一个是public类型的类且该源文件的名字即为这个公有类的名字,且大小写也要一致。其他非public的类的个数不限。 一个Java程序的结构包含以下内容:

  • package语句:包语句,每个文件最多只有一个,且必须放在文件开始的地方。
  • import语句:引入语句,可以没有,也可以有多个,如果有import语句的话,必须放在所有类定义的前面。
  • 具有public权限的类定义:每个文件中最多有一个。
  • 类定义:每个文件中包含的非public权限的类定义的个数没有限制。
  • 接口定义:每个文件中包含的接口定义个数没有限制。

1.1. Java包的概念

  1. 包是类的容器,包的设计人员利用包来划分名字空间,以避免类名冲突。程序员也可以定义自己的包,可以使用package语句来命名。 包语句的格式为:package pkg1[.pkg2[.pkg3...]];
  2. 程序中如果有package语句,该语句一定是源文件中的第一条非注释语句,它的前面只能有注释或空行。另外,一个文件中最多只能有一条package语句
  3. 包的名字有层次关系,各层之间以点分隔。包层次必须与Java开发系统的文件系统结构相同。通常包名中全部用小写字母。一个包要放在指定目录下,通常用CLASSPATH指定搜寻包的路径。类名就是文件名,包名就是文件夹名,即目录名。

1.2. 引入语句

  1. 引入语句的格式如下:import pkg1[.pkg2[.pkg3...].(类名|*); 其中,格式语句中如果指明具体的类名,则表示引入的是这个具体的类;要引入包中的所有类时,可以使用通配符*

    1
    2
    
    import java.util.*;	//引入包中的所有类
    import java.util.ArrayList;	//只引入了包中的ArrayList类
    
  2. 源文件中,可以同时出现package语句和import语句,但要特别注意它们的次序。package语句在import语句之前,且最多只能有一个package语句。

  3. 实际上,程序中并不一定要有引入语句。当引用某个类的类与被引用的类存储在同一个物理目录下时,可以直接使用被引用的类。

2 流程控制语句

2.1. 赋值语句

2.1.1. 概念

赋值语句:表达式可以当作一个值赋给某个变量,这样的语句称为赋值语句。

表达式语句:有的表达式也可单独当作语句,这样的语句称为表达式语句。

2.1.2. 语句与表达式的异同点

  1. 有的表达式可以当作语句,但并不是所有的语句都是表达式;
  2. 每个表达式都会得到一个值,即表达式的计算结果。虽然语句也会有一个值,但这个值并不是语句的计算结果,而是执行结果。

2.2. 分支语句

2.2.1. if语句

if 语句是单重选择,最多只有两个分支。if语句的基本格式是

1
2
3
4
5
if(条件表达式)
	语句1;
[else
	语句2;
]

注意:

  1. if关键字之后的条件表达式必须得到一个逻辑值
  2. if语句中的else子句是可选的,语句1和语句2可以是任意的语句,且只能是一条语句。如果想写多条语句时,需要使用大括号{ }把多条语句组成一个块。
  3. 语句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语句可选        
    ]        
}

注意:

  1. 这里,表达式的计算结果必须是int型或char型,即是int型赋值相容的。当用byte型或short型时,要进行提升。Java规定switch语句不允许使用浮点型或long型表达式。c1,c2…,ck是int型或字符型常量。default子句是可选的,并且,最后一个break语句完全可以不写。
  2. 如果没有相匹配的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类语句中:

  1. 在switch语句中。

  2. 在for、while及do等循环语句中。

  3. 在语句块中。在switch语句及循环语句中,break的语义是跳过本块中余下的所有语句,转到块尾,执行其后的语句。

break语句的第三种使用方法是在块中和标号配合使用,其语法格式为:

1
break 标号;

其语义是跳出标号所标记的语句块,继续执行后面的语句。这种形式的break语句多用于嵌套块中,控制从内层块跳到外层块之后。

2.4.3. continue语句

在循环语句中,continue语句可以立即结束当次循环,开始执下一次循环,当然执行前要先判断循环条件是否满足。 continue语句也可以和标号一起使用,其语法格式为:

1
continue 标号;

它立即结束标号标记的那重循环的当次执行,开始下一次循环。这种形式的语句多用于多重循环中。

3 简单的输入/输出

3.1. Scanner类

  1. Scanner类属于java.util包。它提供了许多方法,可用来方便地读入不同类型的输入值。比如从键盘输入、从文件中输入等。

    image-20230314165545927

  2. 创建一个Scanner类对象,它读入键盘输入:

    1
    
    Scanner scan = new Scanner(System.in);
    

    注意:

    1. Scanner类的构造方法接收一个参数,这个参数代表了输入源。System.in对象代表标准输入流,默认是指键盘。
    2. Scanner对象用空白(空格、水平制表符及回车换行符)作为输入的分隔元素。这些空白称为分隔符。也可以指定用其他的符号作为分隔符。
  3. Scanner类的方法 next()方法读入下一个输入对象,将它作为字符串返回。空格分割。 nextLine()方法读入当前行的所有输入,直到行尾,然后作为字符串返回。

3.2. NumberFormat类和DecimalFormat类

Java提供的格式化输出功能:

  1. NumberFormat类提供对数值进行格式化操作的一般功能。不能使用new运算符实例化一个NumberFormat对象,只能直接使用类名调用一个特殊的静态方法来得到一个对象。 NumberFormat类中常用的方法如下:

    • getInstance():返回当前默认语言环境的默认数值格式。
    • getCurrencylnstance():返回当前默认语言环境的通用格式。
    • getNumberInstance():返回当前默认语言环境的通用数值格式。
    • getPercentInstance():返回当前默认语言环境的百分比格式。
    • setMaximumFractionDigits(int):设置数值的小数部分允许的最大位数。
    • setMaximumIntegerDigits(int):设置数值的整数部分允许的最大位数。
    • setMinimumFractionDigits(int):设置数值的小数部分允许的最小位数。
    • setMinimumIntegerDigits(int):设置数值的整数部分允许的最小位数。

    image-20230316144157331

  2. 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类的子类。

image-20230316151554797

  1. 受检异常,必须被处理。 受检异常(Checked Exception )是程序执行期间发生的严重的后果。发生的原因可能是用户给程序提供了一个错误的文件名。 Java类库中的下列类表示受检异常: ClassNotFoundException 、FileNotFoundException、IOException、NoSuchMethodException及WriteAbortedException

  2. 运行时异常,不需要处理。 运行时异常(Runtime Exception)通常是程序中逻辑错误的结果。例如,数组下标越界导致ArrayIndexOutOfBounds异常。被0除导致ArithmeticException异常。 Java类库中的下列类表示运行时异常: ArithmeticException 、ArraylndexOutOfBoundsException、ClassCastException、EmptyStackException、lllegalArgumentException、IllegalStateException、IndexOutOfBoundsException、NoSuchElementException、NullPointerException和UnsupportedOperationException
  3. 错误,不需要处理。 错误(Error)是标准类Error或其后代类的一个对象,Error是Throwable的后代。一般地,错误是指发生了不正确的情况,如内存溢出。这些情况都比较严重,一般不处理它们。
  4. 很多异常类都在包java.lang中,所以不需要引入。但有些异常类在另外的包中,它们必须要引入。例如,当在程序中使用类IOException时,必须要使用引入语句:import java.io.IOException;

4.3. 异常处理

  1. 当发生异常时,程序通常会中断执行,并输出一条信息。对所发生的异常进行的处理就是异常处理。异常处理的重要性在于,程序不但能发现异常,还要能捕获异常。
  2. 对于可能引发受检异常的方法,有两种选择:在方法内处理异常,或是告诉方法的调用者来处理。
  3. 处理异常的代码 含有两段:第一段try块含有可能抛出异常的语句。第二段含有一个或多个catch块。每个catch块含有捕获及处理某种类型异常的代码。

4.4. 公共异常

  1. ArithmeticException:整数除法中,如果除数为0,则发生该类异常。
  2. NullPointerException:如果一个对象还没有实例化,那么访问该对象或调用它的方法将导致该类异常。
  3. NegativeArraySizeException:创建数组时,如果元素个数是负数,则会引发该类异常。
  4. ArrayIndexOutOfBoundsException:Java把数组看作是对象,并用length变量记录数组的大小。如果数组下标越界,则将导致该类异常。

4.5. 抛出异常

  1. 程序员处理异常有两种方法:

    • 使用try块和catch块,捕获到所发生的异常类,并进行相应的处理。

    • 程序员不在当前方法内处理异常,而是把异常抛出到调用方法中。

  2. 方法内执行throw语句时会抛出一个异常,一般的形式如下。
    1
    2
    3
    4
    
      throw exception_object;
      //throw语句创建了一个异常对象exception_object,如:
      throw new IOException();
      //这个语句创建类IOException的一个新对象并抛出它。抛出异常时也应该尽可能地具体
    
  3. 在方法头中用Java保留字throws来声明这个方法可能抛出的异常;在方法体中用保留字throw实际抛出一个异常。这两个保留字不要弄混。
本文由作者按照 CC BY 4.0 进行授权

Java程序设计精讲一 第二章 数据和表达式

Java程序设计精讲三 第四章 面向对象程序设计