目录
七.异常(Exception)处理
1.异常的概念
在进行程序设计时,错误的产生是不可避免的,如何处理错误?把错误交给谁去处理?程序又该如何从错误中恢复?这是任何程序设计语言都要解决的问题。
所谓异常(也称例外),是在程序运行过程中发生的、会打断程序正常执行的事件。
为了加强程序的健壮性,程序设计时,必须考虑到可能发生的异常事件并做出相应的处理。
如:除0溢出、数组越界、文件找不到
2.异常的分类(Error/Exception)
一个异常是由一个对象来代表的,所有的异常类都直接或间接地继承自Throwable类。
在Java类库的每个包中都定义了异常类,这些异常类分成两大类:Error类及Exception类。
除了使用Java类库所定义的异常类之外,用户也可以通过继承已有的异常类来定义自己的异常类。
- Error:描述和Java虚拟机相关的异常,由Java虚拟机生成并抛出,包括系统崩溃、动态链接失败、虚拟机错误等,Java程序自身不做处理。
- Runtime Exception:在程序运行时产生的异常,如被0除、数组下标越界等,一般由程序设计和实现而引起,其产生比较频繁,数量较多,只能修改程序,运行时程序自己无法处理。
- 非Runtime Exception:程序中可预知的问题,其产生的异常可能会带来意想不到的结果,因此Java编译器要求Java程序必须自己捕获所有的非运行时异常。
(1)Throwable类的方法
- Throwable()
- Throwable(String message)
- String toString() “classname” : “getMessage()”
- String getMessage()
- String getLocalizedMessage()
- void printStackTrace()
- void printStackTrace(PrintStream s)
- void printStackTrace(PrintWriter s)
- Throwable fillInStackTrace()
3.异常处理机制
在程序中处理异常是通过3个关键词来实现的:try-catch-finally。
用try来监视执行一段程序,如果出现异常,系统就会抛出(throw)异常,可以通过异常的类型来捕捉(catch)并处理它,或者最后(finally)由缺省处理方法来处理。
(1) try语句
try语句
- try {…}语句块指定了一段代码,该段代码就是捕获并处理异常的范围。
- 如果没有异常产生,所有的catch代码段都被略过不执行。
(2)catch语句
catch语句
- 每个try语句必须伴随一个或多个catch语句,用于捕获try代码块所产生的异常并做相应的处理。
- 多个catch语句的排列顺序应该按照异常的类型“从特殊到一般”,否则,放在后面的语句将永远执行不到。
(3)finally语句
finally语句
- 无论try所指定的语句块中是否抛出异常,也无论抛出的异常是否已被catch捕获,finally所指定的代码都要被执行,它为异常处理提供了统一的出口。
- 通常在finally语句中可以进行资源的释放工作,如关闭打开的文件、删除临时文件等。
finally在文件访问时非常有用
异常的覆盖
finally代码段中要把可能产生 异常的语句用try-catch保护起来,防止finally代码段抛出异常
4.声明抛弃异常
如果在一个方法中生成了异常,但是该方法并不处理它,而是交由调用它的方法来处理,这就是声明抛弃异常。
声明抛弃异常的方法
对于非运行时异常,程序中必须要作处理,或者捕获,或者声明抛弃;而对于运行时异常,程序中则可不处理。
5.抛出异常(throw语句)
我们在程序中也可以生成自己的异常对象,也即是异常可以不是出错产生,而是人为地抛出。
不论哪种方式,抛出异常对象都是通过throw语句实现:
抛出的异常必须是Throwable或其子类的实例。
6.创建自己的异常
在程序中,可以使用Java类库中已经定义好异常的类,也可以自己定义异常类。
自定义异常类不是由Java系统监测的,而是由用户自己生成并捕获。
7.小结
Java的异常处理机制的优点:
1.提高程序的健壮性。
2.处理异常的代码和“常规”代码分离,增强了程序的可读性。
3.产生异常的代码和处理异常的代码分离,使得可以对异常进行统一的处理。
8.题目
(1)单选题
1.1 关于Java中异常的叙述,正确的是:( )。
A.异常是程序编写过程中代码的语法错误
B.异常是程序编写过程中代码的逻辑错误
C.异常出现后程序的运行马上中止
D.异常是可以捕获和处理的
1.2 以下对异常的描述不正确的有
A.异常分为Error和Exception
B.Throwable是所有异常类的父类
C.Exception是所有异常类父类
D.Exception包括RuntimeException和RuntimeException之外的异常
1.3 Java异常类(Exception)是( )的子类。
A.RuntimeException
B.Exception
C.Error
D.Throwable
1.4 在异常处理时,将可能发生异常的代码放在( )语句块中,后面紧跟着一个或多个( )语句块,还可以再跟零个或一个( )语句块。
A.catch、try、finally
B.try、catch、finally
C.try、finally、exception
D.exception、try、finally
1.5 关于try语句对应的多个catch子句中,若捕获的异常类型有父子类关系时,它们的排列下列哪种是正确的( ) 。
A.异常父类在先,异常子类在后
B.异常子类在先,异常父类在后
C.有继承关系的异常不能同时出现在同一个try程序段之后
D.先后顺序无所谓
1.6 在异常处理中,如释放资源、关闭文件、关闭数据库等由( )来完成。
A.try子句
B.catch子句
C.finally子句
D.throw子句
1.7 假设方法unsafe() 将抛出IOException, 可以填入如下代码段第1行的选项是( )。
1) 2) { if(unsafe()){//do something…} 3) else if(safe()){//do the other…} 4) }
A.public IOException methodName()
B.public void methodName()
C.public void methodName() throw IOException
D.public void methodName() throws IOException
1.8 对以下程序进行编译、运行结果是
abstract class MineBase {
abstract void amethod();
static int i;
}
public class Mine extends MineBase{
public static void main(String argv[]){
int[] ar = new int[5];
for(i = 0;i < ar.length;i++)
System.out.println(ar[i]);
}
}
A.打印5个0。
B.编译出错,数组ar[]必须初始化。
C.编译出错。
D.出现IndexOutOfBoundes的异常
1.9 程序异常
public class Test {
public static void main(String[] args) {
try {
String s = "5.6";
Integer.parseInt(s); // 引起一个 NumberFormatException异常
int i = 0;
int y = 2 / i;
}
catch (Exception ex) {
System.out.println("NumberFormatException");
}
catch (RuntimeException ex) {
System.out.println("RuntimeException");
}
}
}
该程序会出现( )
A.程序显示NumberFormatException。
B.程序显示RuntimeException。
C.程序显示NumberFormatExceptio,然后是RuntimeException。*
D.程序编译错误。
1.10 下列程序的运行结果是( )。
public class Test {
public static void main(String[] args) {
try {
System.out.println("Welcome to Java");
int i = 0;
int y = 2 / i;
System.out.println("Welcome to HTML");
}
finally {
System.out.println("The finally clause is executed");
}
}
}
A.Welcome to Java, 然后是错误信息
B.Welcome to Java,下一行是 The finally clause is executed , 然后是错误信息.
C.替换为正确项
D.替换为错误项
1.11 Java中用来抛出异常的关键字是:( )。
A.try
B.catch
C.throw和throws
D.finally
(2)填空题
2.1 请写出以下程序运行结果:
public class Main {
public static void main(String[] args) {
String s = "hello";
try {
s = s+" world";
s.toUpperCase();
String[] a = s.split("o");
System.out.println(a.length);
} catch (Exception e) {
System.out.print(s);
} finally {
System.out.print(s);
}}}
3
hello world
(3)程序填空题
3.1 异常抛出与捕获案例--下面程序抛出了一个“异常”并捕捉它。请在横线处填入适当内容完成程序。
下面程序抛出了一个“异常”并捕捉它。请在横线处填入适当内容完成程序。
class Main {
static void procedure() throws IllegalAccessException {
System.out.println("inside procedure");
throw //2 分 new //1 分 IllegalAccessException("demo");
}
public static void main(String args[]) {
try {
procedure();
} catch ( IllegalAccessException e //2 分) {
System.out.println("捕获:" + e);
}
}
}
(4)编程题
4.1 设计一个Tiangle异常类
创建一个IllegalTriangleException类,处理三角形的三边,任意两边之和小于等于第三边,则显示三条边不符合要求。
然后设计一个有三条边的Triangle的类。如果三条边不符合要求,则抛出一个IllegalTriangleException异常。
三角形的构造方法如下:
public Triangle(double side1, double side2, double side3) throws IllegalTriangleException {
//实现
}
一个名为toString()的方法返回这个三角形的字符串描述。
toString()方法的实现如下所示:
return "Triangle [side1=" + side1 + ", side2=" + side2 + ", side3=" + side3 + "]";
编写一个测试程序如下,用户输入三角形的三条边,然后显示相应信息。
提交时,将此测试程序附在后面一起提交。
测试程序:
public class Main{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double s1 = input.nextDouble();
double s2 = input.nextDouble();
double s3 = input.nextDouble();
try {
Triangle t = new Triangle(s1,s2,s3);
System.out.println(t);
}
catch (IllegalTriangleException ex) {
System.out.println(ex.getMessage());
}
}
}
输入格式:
输入三条边
输出格式:
如果三条边正确,则输出toString()的信息,否则,输出IllegalTriangleException: 非法的边长
例如,输入1 1 1,则输出Triangle [side1=1.0, side2=1.0, side3=1.0]
若输入 1 2 3,则输出Invalid: 1.0,2.0,3.0
输入样例:
在这里给出一组输入。例如:
1 2 3
输出样例:
在这里给出相应的输出。例如:
Invalid: 1.0,2.0,3.0
代码:
import java.util.*;
class IllegalTriangleException extends Exception{
double side1;
double side2;
double side3;
public IllegalTriangleException(double side1, double side2, double side3){
super("Invalid: "+side1+","+side2+","+side3);//message是父类成员变量,使用super向上传参!
this.side1=side1;
this.side2=side2;
this.side3=side3;
}
}
class Triangle{
double side1;
double side2;
double side3;
public Triangle(double side1, double side2, double side3)
throws IllegalTriangleException {
if((side1+side2)>side3 && (side1+side3)>side2 && (side3+side2)>side1){
//实现
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}
else{
throw new IllegalTriangleException(side1,side2,side3);
}
}
public String toString(){
return "Triangle [side1=" + side1 + ", side2=" + side2 + ", side3=" + side3 + "]";
}
}
public class Main{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double s1 = input.nextDouble();
double s2 = input.nextDouble();
double s3 = input.nextDouble();
try {
Triangle t = new Triangle(s1,s2,s3);
System.out.println(t);
}
catch (IllegalTriangleException ex) {
System.out.println(ex.getMessage());
}
}
}