------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、学习目的
本模块学习结束后,能够:
- 定义异常
- 使用try,catch和finally语句
- 描述异常分类
- 开发程序来处理自己的异常
二、什么是异常
什么是异常?在Java编程语言中,异常类定义程序中可能遇到的轻微的错误条件。可以写代码来处理异常并继续程序执行,而不是让程序中断。
在程序执行中,任何中断正常程序流程的异常条件就是错误或异常。例如,发生下列情况时,会出现异常:
- 想打开的文件不存在
- 网络连接中断
- 受控操作数超出预定范围
- 非常感兴趣地正在装载的类文件丢失
在Java编程语言中,错误类定义被认为是不能恢复的严重错误条件。在大多数情况下,当遇到这样的错误时,建议让程序中断。
Java编程语言实现C++异常来帮助建立弹性代码。在程序中发生错误时,发现错误的方法能抛出一个异常到其调用程序,发出已经发生问题的信号。然后,调用方法捕获抛出的异常,在可能时,再恢复回来。这个方案给程序员一个写处理程序的 选择,来处理异常。
通过浏览API,可以决定方法抛出的是什么样的异常。
三、实例
四、异常处理考虑一下HelloWorld.java程序版本的简单扩展,它通过信息来循环:
<span style="font-family:SimSun;font-size:14px;">public class HelloWorld { public static void main (String args[]) { int i = 0; String greetings [] = { "Hello world!", "No, I mean it!", "HELLO WORLD!!" }; while (i < 4) { System.out.println (greetings[i]); i++; } } } </span>
运行这个程序,在其循环被执行四次之后,异常被抛出,程序终止,并带有错误信息,就象下面所示那样。
<span style="font-family:SimSun;font-size:14px;">1. c:\student\> java HelloWorld 2. Hello world! 3. No, I mean it! 4. HELLO WORLD!! 5. java.lang.ArrayIndexOutOfBoundsException: 3 6. at HelloWorld.main(HelloWorld.java:12) </span>
实际上,异常处理允许应用程序捕获异常并处理它们,然后决定继续程序执行或终止。并且,错误情况的处理代码段不会介入到程序的正常流程中。特殊情况发生时,在与正常执行的代码分离的代码块中被处理。这就产生了更易识别和管理的代码。
五、异常分类try和catch语句
<span style="font-family:SimSun;font-size:14px;"> try { // code that might throw a particular exception } catch (MyExceptionType e) { // code to execute if a MyExceptionType exception is thrown } catch (Exception e) { // code to execute if a general Exception exception is thrown }</span>
要处理特殊的异常,将能够抛出异常的代码放入try块中,然后创建相应的catch块的列表,每个可以被抛出异常都有一个。如果生成的异常与catch中提到的相匹配,那么catch条件的块语句就被执行。在try块之后,可能有许多catch块,每一个都处理不同的异常。
<span style="font-family:SimSun;font-size:14px;">try { // code that might throw a particular exception } catch (MyExceptionType e) { // code to execute if a MyExceptionType exception is thrown } catch (Exception e) { // code to execute if a general Exception exception is thrown } </span>
调用栈机制
如果方法中的一个语句抛出一个没有在相应的try/catch块中处理的异常,那么这个异常就被抛出到调用方法中。如果异常也没有在调用方法中被处理,它就被抛出到该方法的调用程序。这个过程要一直延续到异常被处理。如果异常到这时还没被处理,它便回到main(),而且,即使main()不处理它,那么,该异常就异常地中断程序。
考虑这样一种情况,在该情况中main()方法调用另一个方法(比如,first()),然后它调用另一个(比如,second())。如果在second()中发生异常,那么必须做一个检查来看看该异常是否有一个catch;如果没有,那么对调用栈(first())中的下一个方法进行检查,然后检查下一个(main())。如果这个异常在该调用栈上没有被最后一个方法处理,那么就会发生一个运行时错误,程序终止执行。
finally语句
<span style="font-family:SimSun;font-size:14px;"> try { startFaucet(); waterLawn(); } finally { stopFaucet(); } </span>
finally语句定义一个总是执行的代码块,而不考虑异常是否被捕获。
<span style="font-family:SimSun;font-size:14px;">try { startFaucet(); waterLawn(); } finally { stopFaucet(); }</span>
在前面的例子中,即使异常在打开开关或给草地浇水时发生,开关也能被关掉。try 后面的括号中的代码被称做保护码。
如果终止程序的System.exit()方法在保护码内被执行,那么,这是finally语句不被执行的唯一情况。这就暗示,控制流程能偏离正常执行顺序,比如,如果一个return语句被嵌入try块内的代码中,那么,finally块中的代码应在return前执行。
六、处理或声明规则在Java编程语言中,异常有三种分类。Java.lang.Throwable类充当所有对象的父类,可以使用异常处理机制将这些对象抛出并捕获。在Throwable类中定义方法来检索与异常相关的错误信息,并打印显示异常发生的栈跟踪信息。它有Error和Exception两个基本子类,如下图所示:
Throwable类不能使用,而使用子类异常中的一个来描述任何特殊异常。每个异常的目的描述如下:
- Error表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
- RuntimeException表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。比如,如果数组索引扩展不超出数组界限,那么,ArrayIndexOutOfBoundsException异常从不会抛出。比如,这也适用于取消引用一个空值对象变量。因为一个正确设计和实现的程序从不出现这种异常,通常对它不做处理。这会导致一个运行时信息,应确保能采取措施更正问题,而不是将它藏到谁也不注意的地方。
- 其它异常表示一种运行时的困难,它通常由环境效果引起,可以进行处理。例子包括文件未找到或无效URL异常(用户打了一个错误的URL),如果用户误打了什么东西,两者都容易出现。这两者都可能因为用户错误而出现,这就鼓励程序员去处理它们。
- 用try-catch-finally块来处理异常
- 使用throws子句声明代码能引起一个异常
为了写出健壮的代码,Java编程语言要求,当一个方法在栈(即,它已经被调用)上发生Exception(它与Error或RuntimeException不同)时,那么,该方法必须决定如果出现问题该采取什么措施。
程序员可以做满足该要求的两件事:
第一,通过将Try{}catch(){}块纳入其代码中,在这里捕获给被命名为属于某个超类的异常,并调用方法处理它。即使catch块是空的,这也算是处理情况。
第二,让被调用的方法表示它将不处理异常,而且该异常将被抛回到它所遇到的调用方法中。它是按如下所示通过用throws子句标记的该调用方法的声明来实现的:
public void troublesome() throws IOException
关键字throws之后是所有异常的列表,方法可以抛回到它的调用程序中。尽管这里只显示了一个异常,如果有成倍的可能的异常可以通过该方法被抛出,那么,可以使用逗号分开的列表。
是选择处理还是选择声明一个异常取决于是否给你自己或你的调用程序一个更合适的候选的办法来处理异常。
七、创建自己的异常
用户定义异常是通过扩展Exception类来创建的。这种异常类可以包含一个“普通”类所包含的任何东西。下面就是一个用户定义异常类例子,它包含一个构造函数、几个变量以及方法:
public class ServerTimedOutException extends Exception { private String reason; private int port; public ServerTimedOutException (String reason,int port){ this.reason = reason; this.port = port; } public String getReason() { return reason; } public int getPort() { return port; } }
使用语句来抛出已经创建的异常:
throw new ServerTimedOutException ("Could not connect", 80);
考虑一个客户服务器程序。在客户代码中,要与服务器连接,并希望服务器在5秒钟内响应。如果服务器没有响应,那么,代码就如下所述抛出一个异常(如一个用户定义的ServerTimedOutException)。
public void connectMe(String serverName) throws ServerTimedOutException { int success; int portToConnect = 80; success = open(serverName, portToConnect); if (success == -1) { throw new ServerTimedOutException( "Could not connect", 80); } }
要捕获异常,使用try语句:
public void findServer() { . . . try { connectMe(defaultServer); } catch(ServerTimedOutException e) { System.out.println("Server timed out, trying alternate"); try { connectMe(alternateServer); } catch (ServerTimedOutException e1) { System.out.println("No server currently available"); } }
也可能部分地处理一个异常然后也将它抛出。如:
try { .......... } catch (ServerTimedOutException e) { System.out.println("Error caught "); throw e; }