java学习之路 之 异常处理

时间:2021-10-06 09:09:59

异常处理

在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,
比如:客户输入数据的格式,读取文件是否存在,网络是否始终保持通畅等等。

异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)Java程序在执行过程中所发生的异常事件可分为两类:
Error:  Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。
Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:
空指针访问
试图读取不存在的文件
网络连接中断

异常的类型分类

异常按照类型分为两大类:
受检异常
非受检异常
受检异常是指程序中必须接受检查和处理的异常,由Exception 类表示。
非受检异常是程序中可以不接受检查和处理,或致命性错误异常,由RuntimeException类或Error类表示。

异常的分类:

java学习之路 之 异常处理

常见异常:

java.lang.RuntimeException 
ClassCastExceptio
nArrayIndexOutOfBoundsException
NullPointerException
ArithmeticException
......
java.io.IOExeption
FileNotFoundException
EOFException
java.lang.ClassNotFoundException
java.lang.InterruptedException
java.io.FileNotFoundException
java.sql.SQLException

异常的堆栈式抛出机制:

java学习之路 之 异常处理

为保证程序正常执行,代码必须对可能出现的异常进行处理。

异常对象的生成:
由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象
并抛出——自动抛出
由开发人员手动创建:Exception exception = new ClassCastException();——创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样

对异常的处理:

java.lang.Throwable类为所有异常类的父类。
在编写异常处理程序时,不应使用Throwable类
应使用其不同的子类异常以表示特定的异常错误
Throwable类定义的以下方法可应用在对其各子类异常的处理上:
public String getMessage()
public void printStackTrace()
通常有三种处理异常的方式:
捕获(使用try-catch-finally语句)
直接抛出(方法声明)
捕获再抛出
以上处理方式适用于Exception类型的受检异常和RuntimeException类型的
非受检异常。受检异常必须由程序显式处理

异常处理是通过try-catch-finally语句实现的。
try{  
...... //可能产生异常的代码
} catch(异常类型1 e ){
...... //当产生异常类型1型异常时的处置措施
} catch(异常类型2 e ){
...... //当产生异常类型2型异常时的处置措施
} [ finally{
...... //无论是否发生异常,都无条件执行的语句
} ]

捕获异常:

try
捕获异常的第一步是用try{…}语句块选定捕获异常的范围,将可能出现异常的代码放在try语句块中。
catch (Exceptiontype e)
在catch语句块中是对异常对象进行处理的代码。每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。

如果明确知道产生的是何种异常,可以用该异常类作为catch的参数;也可以用其父类作为catch的参数。        
比如:可以用ArithmeticException类作为参数的地方,就可以用RuntimeException类作为参数,或者用所有异常的父类Exception类作为参数。但不能是与ArithmeticException类
无关的异常,如NullPointerException(catch中的语句将不会执行)。

捕获异常的有关信息:
与其它对象一样,可以访问一个异常对象的成员变量或调用它的方法。
getMessage()   获取异常信息,返回字符串
printStackTrace()  获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。

java学习之路 之 异常处理

finally
捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。
不论在try代码块中是否发生了异常事件,catch语句是否执行,catch语句是否有异常,catch语句中是否有return,finally块中的语句都会被执行。
finally语句和catch语句是任选的
处理过程:Try中检测到异常会将异常对象传递给catch,catch捕获到异常进行处理。Finally里通常用来关闭资源。比如:数据库资源,IO资源等。

class TestException {


public static void main(String[] args) {
try {
int n = Integer.parseInt(args[0]);
System.out.println("n = " + n);
} catch (NumberFormatException e) {
System.out.println("捕获第一个异常:" + e);
System.out.println(e.getMessage());
} catch (ArrayIndexOutOfBoundsException e){
System.out.println("捕获第二个异常:" + e);
System.out.println(e.getMessage());
}
System.out.println("Hello World! -- end");
}
}

主动抛出异常:

throw语句可用来从方法中主动抛出指定异常对象
可以主动抛出RuntimeException及其子类的异常对象。例如:
throw new RuntimeException("Could not connect");
throw语句执行后,方法返回(相当于执行了return语句)
异常对象的printStackTrace()方法可打印输出方法调用的栈踪迹

重写方法声明抛出异常的原则:

重写方法不能抛出比被重写方法范围更大的异常类型。在多态的情况下,对methodA()方法的调用-异常的捕获按父类声明的异常处理。

人工抛出异常:

Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要人工创建并抛出。
首先要生成异常类对象,然后通过throw语句实现抛出操作(提交给Java运行环境)。
IOException e = new IOException();throw e;
可以抛出的异常必须是Throwable或其子类的实例。下面的语句在编译时将会产生语法错误:       
throw new String("want to throw");

创建用户自定义异常类:
很多情况下,需要创建应用程序特定的异常类,以利于可维护性的需要。
例如:       
public class DividedByZeroException extends Exception {        
public DividedByZeroException(String message) {
super(message);
}
public DividedByZeroException(Exception cause) {
super(cause);
}
}

如果方法可能抛出受检异常,那么在方法声明中必须显式指明:     
public double divide(int x, int y) throws DividedByZeroException {

}
如果可能抛出多个异常,应使用逗号将这些异常分隔表示:
public double divide(int x, int y) throws DividedByZeroException, OtherException {

}
也可以声明抛出涵盖这些异常的父类异常:
public double divide(int x, int y) throws Exception {

}

捕获并抛出异常:

一些情况下,会先捕获异常,然后将该异常包装为自定义异常,再抛出给调用者。
例如:
try {            
result = x/y;
} catch (ArithmeticException e) {
throw new DividedByZeroException(e);
}