Java-异常处理(5)
 
 
 
一、 Java异常基础
1.1 为什么要引入异常处理机制?
程序的错误分为:
编译错误:程序员编写程序时语法上出现的错误;
运行错误:程序员编写的程序在语法上没有错误,但是程序在运行时出现错误,本章就主要针对该类错误讲解 - - 即异常、异常类和异常处理机制。
 
1.2 以往的错误处理方法
**主要缺陷:** 程序复杂 可靠性差 返回信息有限 返回代码标准化困难 以往的程序开发过程中,常常采用**返回值**进行处理。例如,在编写一个方法,可以返回一个状态代码,调用者 根据状态代码判断出错与否。若状态代码表示一个错误,则调用该错误的处理程序进行相应的处理,或显示一 个错误页面或错误信息。 |
举例 以往的错误处理方法:采用返回值进行处理
1 | 举例:实现将一个文件从硬盘加载近来,导致加载可能失败的运行错误有硬盘错误、文件无法找到等 |
1 | [例5-2] NonRuntimeExceptionDemo1.java |
 
☕对运行时异常的说明:由于运行时异常可能会出现在程序的任何地方,而且出现的可能性非常大,因而由程序本身去检测运行异常出现与否,将会使程序的开销过大,所以
运行时异常是由Java运行时系统在程序的运行过程中检测到的,它可能在程序中任意部位发生,而且其数目可能很大,因此Java编译器允许程序不对它进行处理。这时,java运行时系统会把生成的运行时异常对象交给默认的异常处理,在标准输出设备上显示异常的内容以及发生异常的位置
建议对于运行时异常用户不要去捕获,捕获就是承认这个错误,但是一般我们编程的希望是发生错误能改正就尽量改正,除非不是由程序员自己意愿决定的错误。
 
☕对运行时异常和非运行时异常的总结:
(1) 当出现java.lang.ArithmeticException运行时异常时,不需要用户在程序中对其进行处理,而直接由Java运行时系统进行处理;
(2) 对于非运行时异常,Java编译器对程序进行编译的时候,便指出用户需要①捕获该类异常或者②声明抛出。即对于非运行时异常,用户需要在程序中进行处理,否则编译时无法通过。
1 | ① 捕获该类异常 |
 
 
2.3 对于运行时异常和非运行时异常的一些说明
1. ☕编译器和异常:编译器强制要求程序员捕获或声明抛出非运行时异常
到底为什么要这么做呢???
对于运行时异常,编译器不强制要求,但用户也可以自己去捕获
这个时候会出现什么效果呢???
2. ☕运行时系统和异常:
(1) 异常都有抛出的轨迹;
(2) 对于所有异常,某个方法产生的异常 ,如果没有被捕获,就会自动抛给方法的调用者(但是对非运行时异常一定要声明抛出),如果调用者还没有捕获,再抛给调用者的调用者,以此类推,直到main方法里发现还没有捕获,那么运行时系统就会来处理这个异常,把异常信息和异常的轨迹信息打印给用户。
3. ☕两点建议:
(1) 建议对于运行时异常用户不要去捕获,捕获就是承认这个错误,但是一般我们编程者希望是发生错误能改正就尽量改正,除非不是由程序员自己意愿决定的错误;
(2) 建议对于非运行时异常,用户应该去捕获,以交代程序员的处理该错误的代码,实在不行,就声明抛出给方法的调用者。
3. ☕异常类常用的方法:
public Exception()
public Exception(String s)  :该参数一般表示该异常对应的错误的描述
public String toString() :返回描述当前异常对象信息的字符串
public String getMessage() :返回描述当前异常对象信息的详细信息。
public void printStackTrace() :打印当前异常对象使用堆栈的轨迹。
 
 
三、 try-catch-finally异常处理
3.1 概括try-catch-finally语句
用户处理异常的三种方法:
(1)用户可以用try-catch-finally语句进行抛出和捕获处理;
(2)如果不想捕获和处理异常,可以通过throws语句声明要抛出的异常;
(3) 用户可以定义自己的异常类,并用throw语句来抛出。
运行时异常是由Java运行时系统在程序的运行过程中检测到的,它可能在程序中任意部位发生,而且其数目可能很大,因此Java编译器允许程序不对它进行处理。这时,java运行时系统会把生成的运行时异常对象交给默认的异常处理,在标准输出设备上显示异常的内容以及发生异常的位置。即:运行时异常:会输出到设备显示哪里存在错误,请更正;非运行时异常:编译报错时提示必须添加非运行时异常处理,比如加try{}…catch(类名 对象){}或者使用throws来抛出异常。
1 | try-catch-finally语句对程序运行进行监控,捕获和处理异常通常形式: |
1 | [例5-3]访问文本文件text.txt,并将其在屏幕上打印出来。 |
 
 
3.2 try语句
☕try{}:将可能抛出一个或者若干个异常的代码放入try语句块中。
注意:应当尽量减小try代码块的大小,不要将整个程序代码全部放入try语句块中,而是应当仔细分析代码,在可能出现异常情况的地方用try进行监控。
因为当发生异常时,程序控制由try块转到catch块,Java将跳过try中后面的语句,且永远不会从catch块返回到try块。因此若将整个程序代码都放在try中,若一开始发生异常,则后面的语句将永远不会被执行,从而影响了程序的实现。
 
3.3 catch语句
**📒(1)** **try语句后面必须跟有一个或多个catch语句来处理try中产生的异常事件**。如果try语句中未产生异常, 那么catch语句将不执行。 **📒(2)catch语句需要一个参数:****一个异常类名和该异常类的对象。注意该异常类必须是Throwable类的子类**. **📒(3)** try块中发生了一个异常,try-catch语句就会自动在try块后面的各个catch块中,找出与该异常类相 匹配的参数。当参数符合以下3个条件之一时,就认为这个参数与产生的异常相匹配: (1)参数与产生的异常属于一个类; (2)参数是产生的异常的父类; (3)参数是一个接口时,产生的异常实现了这一接口。 **📒(4) 注意:** (1) 当产生的异常找到了第一个与之相匹配的参数时,就执行包含这一参数的catch语句中的Java代码,执 行完catch语句后,程序恢复执行,但不会回到异常发生处继续执行,而是执行try-catch结构后面的代码。 (2) 可以用一个catch块来处理多个异常类型,此时catch的参数应该是这多个异常的父类。 (3) 有多个catch块时,要细心安排catch块的顺序。 **将子类的catch块放在前面,父类的catch块放在后面。** |
 
3.4 finally子句
**1.finally语句:** 无论在try块中是否产生异常,也不管产生的异常是否会被捕获,finally中的语句最终都会
被执行。
**2.作用:** 为异常处理事件提供一个清理机制,例如清理打开文件、Socket、JDBC连接之类的资源。
如果程序用到了文件、Socket、JDBC连接之类的资源,即使遇到了异常,也要正确释放占用的资源。 3. 带有finally子句的try-catch-finally语句的形式如下: |
1 | try { … } //…是正常执行的代码, 可能产生异常 |
**4.执行过程:** **(1) try块中的语句没有产生异常。**在这种情况下,Java首先执行try块中的所有的语句,然后执行finally子句 中的代码,最后执行try…catch..finally块后面的语句; **(2) try块中的语句产生了异常,而且此异常在方法内被捕获(有catch匹配)。** 在这种情况下,Java首先执行try 块中的语句,直到产生异常处,然后跳过此try块中剩下的语句,执行捕获此异常的catch子句的处理代码; 然后执行finally子句中的代码; **(3) 如果在catch子句又重新抛出了异常。**也会执行finally,然后将这个异常抛出给方法的调用者; **(4) try块中产生了异常,而此异常在方法内没有被捕获(没有catch匹配) 。**在这种情况下,Java将执行try块 中的代码直到产生异常,然后跳过try块中的代码而转去执行finally子句中的代码,最后将异常抛出给方法 的调用者。 |
 
 
四、 throws-throw抛出异常
4.1 throws抛出异常
📒throws说明:
在设计可能会抛出异常的方法时,可以有两个选择:
(1) 使用try-catch-finally处理方法中的异常;
(2) 声明抛出异常:不捕获异常(没有throws方法的创建异常类的实例和抛出异常。是个空语句。),而是将异常交由上一层处理,在其他地方捕获异常。如果使用后者,那么应该(在某些情况下)向编译器表明:此方法可能会抛出异常,但方法本身不会捕获它。可以在方法头中用throws子句来实现此功能。
(2.1)带throws异常说明的方法说明形式如下:
… 方法名(…) [throws 异常类列表]
{ 方法体 }
 
📒注意:
(1)方法抛出的异常类是throws子句中指定的异常类或其子类。
(2)并不是所有可能发生的异常都要在方法的说明中指定,从Error类中派生出的异常和从RuntimeException类中派生的异常就不用在方法声明中指定。
📒在下列情况下Java方法可以声明抛出异常:
(1)调用的方法抛出了异常;
(2)检测到了错误并使用throw语句抛出异常;
1 | 例1:调用的方法抛出了异常 |
 
 
4.2 throw抛出异常
📒throw说明:
要使用throw,则必须在方法名后面指出throws;但是使用throws,抛出可以是空语句不用写,交给上一层处理!!
在捕获一个异常前,必须有一段Java代码来生成和抛出一个异常对象。Java用throw语句抛出异常。throw语句的格式如下:
throw ThrowableObject;
 
异常对象的生成和抛出可以有以下三种情况:
(1)Java运行时系统
(2)JDK中某个类
(3)在程序中创建异常对象抛出
使用throw语句应注意:
(1)一般这种抛出异常的语句应该在满足一定条件执行,例如把throw语句if分支中
(2)含有throw语句的方法,应该在方法头定义中用throws语句声明所有可能抛出的异常
抛出异常有这样三步:
(1)确定异常类;
(2)创建异常类的实例;
(3)抛出异常。
1 | 举例 |
 
 
五、 正确地使用异常
由于异常使用起来非常方便,以至于在很多情况下可能会滥用异常。但是,使用异常处理会降低程序运行的
速度,几点建议:
(1) 在可以使用简单的测试就能完成的检查中,不要使用异常来代替它。例如: (2) 不要过细地使用异常。最好不要到处使用异常,更不要在循环体内使用异常处理, 可以将它包裹在循环 (4) 将异常保留给方法的调用者并非不好的做法。 |