第八章.异常处理
文章目录:
- 异常处理机制介绍
- 异常类的继承关系
- 异常类
- 异常类型
- 常用的异常类
- 异常的产生
- 异常的处理过程
- try/catch
- 多重catch子句
- finally子句
- throws关键字
- throw抛出异常
- 小总结
1.异常处理机制介绍:
Java提供了异常处理机制来帮助程序员处理可能出现的错误,异常是程序中 的一些错误,但并不是所有的错误都是异常,并且有些错误是可以避免的。我们思考一下编写Java程序时可能会遇到哪些异常或错误问题?我们把编写、运行Java程序时会遇到的错误问题分为三种:语法错误、逻辑错误和运行时错误。
2.异常类的继承关系:
异常是程序执行的时候所遇到的非正常情况或意外行为。一般情况下,如数组下标越界、算法溢出、除数为零等都可以引发异常发生。所有异常类型都是Throwable的子类,Throwable处在异常类层次结构的顶层。它是所有异常类的父类。它有两个子类,即Error 和Exception,它们分别用来处理两组异常。
3异常类:
Object 类的直接子类Throwable描述了所有被虚拟机抛出的非正常状况。一般情况下很少用Throwable
而是用它的两个子类Error、Exception。
Error类特指应用程序在运行期间发生的严重错误。如:虚拟机内存用尽、堆栈溢出等等。
一般情况下这种错误都是灾难性的,所以没有必要使用异常处理机制处理Error。
Exception类有几十个子类,描述了不同类型的异常,其中:
以RuntimeException为代表的一些类,称为非检查性异常(unchecked Exception),用来表示设计或实现方面
的问题,如数组下标越界、除数为零等问题。因为设计和实现正确的程序不会引发这类异常,所以Java并不强
制提前处理它。发生这类异常时,运行时环境会输出一条信息,提示用户如何去修正错误。我们可以利用Java
提供的异常处理机制,对可能出现的异常进行预见性处理,以保证程序的顺利运行而不是异常终止。
以IOException为代表的一些类为检查性异常(checked Exception)。所谓的检查和非检查是指编译器在编译时
是否检查。如果代码中存在检查性异常,必须进行异常处理,否则编译时不能通过;而非检查性异常编译时不
进行检查,到运行时才会显现。因为用户的疏忽很可能导致这类问题在程序运行时发生,比如用户键入的内容
不完整等,所以Java鼓励程序员提前处理它们。
4.异常类型:
①.异常按照处理方式可以分为如下两种类型:
1.检查性异常(checked exception)
若系统运行时可能产生该类异常,则必须写出相应的处理代码,否则无法通过编译。
2.非检查性异常(unchecked exception)
非检查性异常也称之为RuntimeException,若系统运行时可能产生该类异常,则不必在程序中声明对该类异常的处理,就可以编译执行。
②.一般我们不在代码中处理非检查性异常,这类异常都在运行时抛出。原因主要是由于程序员经验不足或是思维不缜密造成。如:数组越界异常(ArrayIndexOutOfBoundsException)、整数除以0异常(ArithmeticException)等,这类异常其实就是我们通常说的bug。所以,这类异常应通过反复测试尽量避免,而不应该靠异常处理机制来解决。
③.检查性异常不同,就算程序员再有经验,也是难以避免。如:用户连接数据库的异常(SQLException),如果是由于数据库服务器没有启动或是网络中断引起的,我们程序员是无法避免的。又如:程序要读取光盘中的文件,而用户忘记插入光盘,此时则抛出文件没找到异常(FileNotFoundException),程序员也无法避免。
综上,异常处理机制主要处理检查性异常而不是非检查性异常和Error。
5.常见的异常类:
package chapter08;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TestException {
public static void main(String[] args) {
// TODO Auto-generated method stub
//语法错误:
//int a = 10;
//String name = "hello"
//逻辑错误
/*int sum = 0;
for(int i =1;i<100;i++){
sum+=i;
}*/
//运行时错误
/*所有异常的父类throwable:Error Exception
* Exception:RuntimeException(非检查性异常,运行时异常):可处理可不处理
* :除了RuntimeException以外的所有子异常都是检查性异常,非运行时异常
*
* */
//算数异常:ArithmeticException 运行时异常 java.lang包下的类不需要导入,特殊
/*try{
int a = 10;
int b = 0;
int c = a/b;
}catch(ArithmeticException e){
e.printStackTrace();
}*/
//文件找不到异常:FileNotFoundException 检查性异常
/*try {
FileInputStream fis = new FileInputStream("d:/qwe.txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//输入不匹配异常:InputMismatchException:运行时异常
try{
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
}catch(InputMismatchException e){
e.printStackTrace();
}
System.out.println("come here");
}
}
6.异常的产生:
Java语言是一种面向对象的编程语言,因此,在Java语言中异常也是作为某种异常类的实例的形式出现的。当在某一方法中发生错误时,运行环境就创建一个异常对象,并且把它传递给系统,我们可以利用Java提供的异常处理机制,捕获这个异常对象,并且可以脱离主程序流程进行处理。我们不但可以捕获系统创建的异常实例,还可以创建自己的异常实例,并可以主动抛出异常实例,达到控制程序执行顺序的作用。
7.异常的处理过程
在Java程序执行过程中如果出现异常事件,系统会发出异常报告,这时系统将生成一个异常类对象,异常类对象封装了异常事件的信息并将其提交给Java运行时系统
Java 中可用于处理异常的两种方式:
自行处理:可能引发异常的语句封入在 try 块内,而处理异常的相应语句则封入在 catch 块内。
回避异常:在方法声明中包含 throws 子句,通知潜在调用者,该方法可能会出现异常,但没有处理这种异常,必须由调用者处理。
8.try/catch.
使用Java提供的异常捕获结构,我们就可以捕获到可能出现的异常,避免程序异常终止。
Java的异常捕获结构由try/catch/finally子句组成.
9.多重catch子句
有时一段程序可能会产生多种异常,这时,我们就可以设置多个catch子句来进行捕获,每个子句都来捕获不同
类型的异常。当有异常发生时,每个catch子句依次被匹配检查,当发生的异常是catch子句所声明的类型或其子
类型时,程序执行流程就转入到该catch子句中继续执行,其余的catch子句将不再检查或执行。
package chapter08;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TestException2 {
/*自行处理:try catch处理
* 1.catch块捕获异常,没有try块catch块不能单独存在
* 2.可以使用多个catch块捕获异常
* 3.子类在前父类异常在后
* */
public void print(){
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int a = 1;
int b = 0;
int c = a/b;
int[] arr = new int[2];
arr[2] = 10;
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
FileInputStream fis = new FileInputStream("d:/aaa.txt");
TestException2 t = null;
t.print();
}catch(ArithmeticException | ArrayIndexOutOfBoundsException e){//也可以在一个catch块中声明多个异常,注意:不能有父子关系
e.printStackTrace();
System.out.println("算数异常");
}catch(InputMismatchException e){
System.out.println("输入不匹配异常");
}catch(FileNotFoundException e){
System.out.println("文件找不到异常");
}catch(RuntimeException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("come here");
}
}
10.finally子句
package chapter08;
public class TestException3 {
/*finally子句:必须执行的代码:关闭资源,关闭和数据库的连接
* try catch
* try finally:如果触发异常走完finally程序再崩掉
* try catch finally
* catch finally:错误,catch块不能脱离try块单独存在
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int a = 10;
int b = 0;
int c = a/b;
}catch(ArithmeticException e){
e.printStackTrace();
return;
}finally{
System.out.println("come");
}
}
}
11.throws关键字
在Java的语法中,如果一个方法中调用了已经声明检查性异常的另一个方法,那么Java编译器会强制调用者必须处理被声明的异常,要么捕获要么继续声明。
12.throw抛出异常