第八章Java的“异常”
来源:互联网 发布:数据分散程度的统计量 编辑:程序博客网 时间:2024/06/06 00:29
“异常”指的是程序运行时出现的非正常情况。
在用传统的语言编程时,程序员只能通过函数的返回值来发出错误信息,这易于导致很多错误。因为在很多情况下需要知道错误产生的内部细节。通常,用全局变量errno来存储“异常”的类型。这容易导致误用,因为一个errno的值有可能在被处理之前被另外的错误覆盖掉。即使最优美的C语言程序,为了处理“ 异常”情况,也常求助于goto语句。
Java对“异常”的处理是面向对象的。一个Java的Exception是一个描述“异常”情况的对象。当出现“异常”情况时,一个Exception对象就产生了,并放到产生这个“异常”的成员函数里。
8.1 基础
Java的“异常”处理是通过5个关键词来实现的:try,catch,throw,throws和finally。
用try来执行一段程序,如果出现“异常”,系统抛出(throws)一个“异常”,你可以通过它的类型来捕捉(catch) 它,或最后(finally)由缺省处理器来处理。
下面是“异常”处理程序的基本形式:
try {
//程 序 块
}catch (ExceptionType1 e){
// 对ExceptionType1的处理
}catch (ExceptionType2 e){
// 对ExceptionType2的处理
throw(e); //再抛出这个“异常”
}
finally { }
8.2 "异常”的类型
在“异常”类层次的最上层有一个单独的类叫做Throwable。这个类用来表示所有的“异常”情况。每个“异常”类型都是Throwable的子类。Throwable有两个直接的子类。
一类是Exception,是用户程序能够捕捉到的“异常”情况。我们将通过产生它的子类来创建自己的“异常”。
另一类是Error,它定义了那些通常无法捕捉到的“异常”。要谨慎使用Error子类,因为它们通常会导致灾难性的失败。
在Exception中有一个子类RuntimeException,它是程序运行时自动地对某些错误作出反应而产生的。
8.3 不捕捉“异常”
“异常”对象是Java在运行时对某些“异常”情况作出反应而产生的。例如,下面这个小程序包含一个整数被0除的“异常”。
class Exc0 {
public static void main(String args[]) {
int d = 0;
int a = 42/d;
}
}
当Java执行这个除法时,由于分母是0,就会构造一个“异常”对象来使程序停下来并处理这个错误情况,在运行时“抛出”(throw)这个“异常”。说“抛出”是因为它象一个滚烫的马铃薯,你必须把它抓住并立即处理。程序流将会在除号操作符处被打断,然后检查当前的调用堆栈来查找“异常”。一个“异常”处理器是用来立即处理“异常”情况的。
在这个例子里,我们没有编一个“异常”处理器,所以缺省的处理器就发挥作用了。缺省的处理器打印Exception的字符串值和发生“异常”的地点。下面是我们的小例子的输出:
C:/>java Exc0 java.lang.arithmeticException: / by zero at Exc0.main(Exc0.java:4)
8.4 try与catch
通常我们希望自己来处理“异常”并继续运行。可以用try来指定一块预防所有“异常”的的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的“异常”的类型。例如,下面的例子是在前面的例子的基础上构造的,但它包含一个try程序块和一个catch子句。
class exc1 {
public static void main(string args[]) {
try {
int d = 0;
int a = 42 / d;
}catch(arithmeticexception e){
system.out.println("division by zero");
}
}
}
catch子句的目标是解决“异常”情况,把一些变量设到合理的状态,并象没有出错一样继续运行。如果一个子程序不处理某个“异常”,则返到上一级处理,直到最外一级。
8.5 多个catch子句
在某些情况下,同一段程序可能产生不止一种“异常”情况。你可以放置多个catch子句,其中每一种“异常”类型都将被检查,第一个与之匹配的就会被执行。如果一个类和其子类都有的话,应把子类放在前面,否则将永远不会到达子类。
下面是一个有两个catch子句的程序的例子。
class MultiCatch {
public static void main(String args[]) {
try {
int a = args.length;
System.out.println("a = " + a);
int b = 42/a;
int c[] = {1};
c[42] = 99;
}catch(ArithmeticException e){
System.out.println("div by 0: " + e);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("array index oob: " + e);
}
}
}
如果在程序运行时不跟参数,将会引起一个0做除数的“异常”,因为a的值为0。如果我们提供一个命令行参数,将不会产生这个“异常”,因为a的值大于0。但会引起一个ArrayIndexOutOfBoundexception的“异常”,因为整型数组c的长度是1,却给c[42]赋值。下面是以上两种情况的运行结果:
C:/>java MultiCatch a = 0 div by 0: java.lang.arithmeticexception: / by zero
C:/>java MutiCatch 1 a = 1 array index oob: java.lang.ArrayIndexOutOfBoundsException:42
8.6 try语句的嵌套
你可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部,写另一个try语句保护其他代码。每当遇到一个try语句,“异常”的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种“异常”进行处理,堆栈就会展开,直到遇到有处理这种“异常”的try语句。
下面是一个try语句嵌套的例子:
class MultiNest {
static void procedure() {
try {
int c[] = { 1 }:
c[42] = 99;
}catch(ArrayIndexOutOfBoundsexception e){
System.out.println("array index oob: " + e);
}
}
public static void main(String args[]) {
try {
int a = args.length;
System.out.println("a = " + a);
int b = 42/a;
procedure();
}catch(arithmeticException e){
System.out.println("div by 0: " + e);
}
}
}
成员函数procedure里有自己的try/catch控制,所以main不用去处理ArrayIndexOutOfBoundsException。
8.7 throw语句
throw语句用来明确地抛出一个“异常”。
首先,你必须得到一个Throwable的实例的控制柄,通过参数传到catch子句,或者用new操作符来创建一个。下面是throw语句的通常形式:
throw ThrowableInstance;
程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中从里向外寻找含有与其匹配的catch子句的try块。下面是一个含有throw语句的例子:
class ThrowDemo {
static void demoproc() {
try {
throw new NullPointerException("de3mo");
}catch(NullPointerException e){
System.out.println("caught inside demoproc");
throw e;
}
}
public static void main(String args[]) {
try {
demoproc();
}catch(NullPointerException e){
system.out.println("recaught: " + e);
}
}
}
8.8 throws语句
throws用来标明一个成员函数可能抛出的各种“异常”。
对大多数Exception子类来说,Java编译器会强迫你声明在一个成员函数中抛出的“异常”的类型。如果“异常”的类型是Error或RuntimeException,或它们的子类,这个规则不起作用,因为这些在程序的正常部分中是不期待出现的。如果你想明确地抛出一个RuntimeException,你必须用throws语句来声明它的类型。这就重新定义了成员函数的定义语法:
type method-name(arg-list) throws exception-list { }
下面是一段程序,它抛出了一个“异常”,但既没有捕捉它,也没有用throws来声明。这在编译时将不会通过。
class ThrowsDemo1 {
static void procedure( ) {
System.out.println("inside procedure");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
procedure( );
}
}
为了让这个例子编译过去,我们需要声明成员函数procedure抛出了IllegalAccessException,并且在调用它的成员函数main里捕捉它。下面是正确的例子:
class ThrowsDemo {
static void procedure( )
throws IllegalAccessException {
System.out.println("inside procedure");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
try {
procedure( );
}catch(IllegalAccessException e){
System.out.println("caught " + e);
}
}
}
下面是输出结果:
C:/>java ThrowsDemo inside procedure caught java.lang.IllegalAccessException: demo
8.9 finally
当一个“异常”被抛出时,程序的执行就不再是线性的,跳过某些行,甚至会由于没有与之匹配的catch子句而过早地返回。有时确保一段代码不管发生什么“异常”都被执行到是必要的,关键词finally就是用来标识这样一段代码的。即使你没有catch子句,finally程序块也会在执行try程序块后的程序之前执行。每个try语句都需要至少一个与之相配的catch子句或finally子句。一个成员函数返回到调用它的成员函数,或者通过一个没捕捉到的“异常”,或者通过一个明确的return语句,finally子句总是恰好在成员函数返回前执行。
下面是一个例子,它有几个成员函数,每个成员函数用不同的途径退出,但执行了finally子句。
class FinallyDemo {
static void procA( ) {
try {
System.out.println("inside procA");
throw new RuntimeException("demo");
}finally{
System.out.println("procA's finally");
}
}
static void procB( ) {
try {
System.out.println("inside procB");
return;
} finally {
System.out.println("procB's finally");
}
}
public static void main(String args[]) {
try {
procA( );
} catch (Exception e)
;
procB( );
}
}
下面是这个例子的运行结果:
C:/>java FinallyDemo inside procA procA's finally inside procB procB's finally
本章小结
1.“异常”指的是程序运行时出现的非正常情况。
2. 在“异常”类层次的最上层的类叫Throwable,它有两个直接的子类:Exception和Error。
3. Java的“异常”处理通过5个关键词来实现:try,catch,throw,throws和finally。
- 第八章Java的“异常”
- 第八章 java的异常处理
- Java语言入门 -- 第八章 Java的“异常”
- 第八章 异常
- 第八章 异常
- [疯狂Java讲义精粹] 第八章|异常处理
- JAVA学习笔记(第八章异常处理)
- 第八章 JAVA的封装
- java集合第八章WeakHashMap的用法
- Thinking in Java 第七章 多态 第八章:接口与内部类 第九章:异常处理
- Java作业第八章
- Java作业第八章
- Java作业第八章
- java第八章
- 《Java核心技术(第八版)》笔记之第11章异常、断言和调试
- CSAPP 第八章:异常控制流 小结
- java第八课_内部类,匿名内部类,异常
- java 第八周的选做题
- 我来啦CSDN
- 免费跟着外教学英语,突破哑巴口语
- ERP 复习 week 1 - tutorial 续
- 9.1 Java输入输出流
- web.xml配置说明
- 第八章Java的“异常”
- 第七章多线程
- 进入'我的电脑'窗口后,左边显示的‘系统任务,其它位置,详细信息’菜单条到删除和出现的问题解决
- 第六章Java图形用户接口
- C++常量的定义规则
- 第五章Java的类
- 第四章Java应用程序的基本框架
- 第三章Java程序设计基础
- 第二章Java程序开发与运行环境