1.JAVA是采用面向对象的方式来处理异常的。
(1).抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给JRE。
(2).捕获异常:JRE得到该异常后,寻找相应的代码来处理该异常。JRE在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到相应的异常处理代码为止。
2.结构图
Error类层次描述了Java运行时系统内部错误和资源耗尽错误。
Exception是所有异常类的父类
RuntimeException是非检查型异常,例如NumberFormatException,可以不使用try...catch进行处理
其他的都是检查型异常,都需要用try...catch处理
3,异常处理的两种办法
异常的处理办法之一,捕获异常
try块
try语句指定了一段代码,该段代码就是一次捕获并处理的范围。在执行过程中,当任意一条语句产生异常时,就会跳过该段中后面的代码。代码中可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句要分别对这些异常做相应的处理
一个try语句必须带有至少一个catch语句块或一个finally语句块 。。
注:当异常处理的代码执行结束以后,是不会回到try语句去执行尚未执行的代码。
catch
a)每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。
b)常用方法:
toString ( )方法,显示异常的类名和产生异常的原因
getMessage( )方法,只显示产生异常的原因,但不显示类名。
printStackTrace( )方法,用来跟踪异常事件发生时堆栈的内容。
这些方法均继承自Throwable类
c)Catch捕获异常时的捕获顺序:
i.如果异常类之间有继承关系,在顺序安排上需注意。越是顶层的类,越放在下面。再不然就直接把多余的catch省略掉。
finally
有些语句,不管是否发生了异常,都必须要执行,那么就可以把这样的语句放到finally语句块中。
通常在finally中关闭程序块已打开的资源,比如:文件流、释放数据库连接等。
举两个简单例子:
package
com.bjsxt.Exception;
import
java.io.FileNotFoundException;
import
java.io.FileReader;
import
java.io.IOException;
public
class
TestException {
public
static
void
main(String[] args) {
FileReader reader =
null
;
try
{
reader =
new
FileReader(
"d:/a.txt"
);
char
temp = (
char
) reader.read();
System.out.println(
"读出的内容:"
+ temp);
}
catch
(FileNotFoundException e) {
System.out.println(
"文件没有找到!!"
);
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
System.out.println(
"文件读取错误!"
);
}
finally
{
System.out.println(
" 不管有没有异常,我肯定会被执行!"
);
try
{
reader.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
}
FileNotFoundException异常是IOException的子类,catch部分的异常应该从从低到高
有return语句的try..catch...finally语句的执行顺序
1.执行try,catch , 给返回值赋值
2.执行finally
3.return
例子:
package
com.bjsxt.Exception;
import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.FileReader;
import
java.io.IOException;
public
class
TestException {
public
static
void
main(String[] args) {
String str =
new
TestException().openFile();
System.out.println(str);
}
String openFile() {
try
{
System.out.println(
"aaa"
);
FileInputStream fis =
new
FileInputStream(
"d:/a.txt"
);
int
a = fis.read();
System.out.println(
"bbb"
);
return
"step1"
;
}
catch
(FileNotFoundException e) {
System.out.println(
"catching !!!!!"
);
e.printStackTrace();
return
"step2"
;
// 先确定返回值,并不会直接结束运行。
}
catch
(IOException e) {
e.printStackTrace();
return
"step3"
;
}
finally
{
System.out.println(
"finally !!!!!"
);
// return "fff";不要在finally中使用return.
}
}
}
假如程序没出现异常,输出结果为:
aaa
bbb
finally !!!!!
step1
假如FileInputStream fis =
new
FileInputStream(
"d:/a.txt"
)出现异常,即出现FileNotFoundException (文件未找到异常),输出结果为
aaa
catching !!!!!
finally !!!!!
step2
如果finally中加上return "fff";这句话,程序运行没出现异常,输出结果为
aaa
bbb
finally !!!!!
fff
解析:因为return语句刚开始只给返回值赋值,执行完finally才返回rerurn语句要返回的值,刚开始return语句赋值为step1,然后return语句赋值为fff替换了step1,所以最后返回fff
异常的处理办法之二,声明异常:throws子句
当Checked Exception产生时,不一定立刻处理它,可以再把异常Throws出去。
在方法中使用try-chatch-finally由这个方法处理异常。在一些情况下,当前方法并不需要处理发生的异常,而是向上传递给调用它的方法处理。
如果一个方法中可能产生某种异常,但是并不能确定如何处理这种异常,则应根据异常规范在方法的首部声明该方法可能抛出的异常。
如果一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常,之间以逗号隔开。
package
com.bjsxt.Exception;
import
java.io.FileNotFoundException;
import
java.io.FileReader;
import
java.io.IOException;
public
class
FileTest {
public
static
void
main(String[] args) {
try
{
readFile(
"d:/a.txt"
);
}
catch
(FileNotFoundException e) {
System.out.println(
"所需要的文件不存在!"
);
e.printStackTrace();
}
catch
(IOException e) {
System.out.println(
"文件读写出错误!"
);
e.printStackTrace();
}
}
public
static
void
readFile(String fileName)
throws
IOException {
FileReader in =
new
FileReader(fileName);
try
{
int
tem =
0
;
tem = in.read();
while
(tem != -
1
) {
System.out.println((
char
) tem);
tem = in.read();
}
}
finally
{
in.close();
}
}
}
readFile方法抛出异常(throws
IOException
),交给调用它的main方法捕获异常
try
{
readFile(
"d:/a.txt"
);
}
catch
(FileNotFoundException e) {
System.out.println(
"所需要的文件不存在!"
);
e.printStackTrace();
}
catch
(IOException e) {
System.out.println(
"文件读写出错误!"
);
e.printStackTrace();
}
}
方法重写中声明异常原则
子类声明的异常范围不能超过父类声明的范围
不可抛出原有方法抛出异常类的父类或上层类
异常的处理办法之三,手动抛出异常,throw子句
Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要手工创建并抛出。
在捕获一个异常前,必须有一段代码先生成异常对象并把它抛出。这个过程我们可以手工做,也可以由JRE来实现,但是他们调用的都是throw子句。
对于一个已经存在的异常类,抛出该类异常对象过程如下:
找到一个合适的异常类。
创建一个该类的对象。
将对象抛出
File f =
new
File(
"c:/tt.txt"
);
if
(!f.exists()) {
try
{
throw
new
FileNotFoundException(
"File can't be found!"
);
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
}
自定义异常
自己定义一个异常,从Exception类或者它的子类派生一个子类即可
最后对使用异常机制建议
(1)不要进行小粒度的异常处理---应该将整个任务包装在一个Try语句块中
简单来说就是一个方法的try语句中写多个可能会出现异常的地方,进行集中处理
(2)异常往往在高层处理