理解Java异常处理机制

版权声明:本文为博主原创文章,转载请注明出处。

1.以下是异常的基本介绍:Java异常层次结构图 如下

       Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类,结构如上图(以上结构图中的子类异常并不是所有的,只是标注了一些重要的常见的异常)。

       Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。

       大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(VirtualMachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。

       Exception(异常):是程序本身可以处理的异常。

       Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。

  Exception 和 RuntimeException 的区别:

    1.Exception 表示程序运行过程中可能出现的非正常状态,RuntimeException表示虚拟机非通常操作中可能遇到的异常,是一种常见运行错误。Java编译器要求方法必须声明抛出可能发生的非运行时异常,但并不要求必须声明抛出未被捕获的运行时异常,即 Exception 定义了必须处理的异常,而 RuntimeException 定义的异常可以选择性的进行处理。

    2.RuntimeException 是 Exception 的子类。

2.异常的处理

  在Java中,如果某个方法抛出异常,既可以在当前方法中进行捕捉,然后处理该异常,也可以将该异常向上抛出,由方法调用者来处理。

  a>.Java的异常捕获结构由try、cache和finally3个部分组成,例如:

 1 try {
 2     // 可能会抛出异常的代码块
 3     int result = 2 / 0;
 4     System.out.print("运算结果:" + result);
 5 } catch (ArithmeticException e) {
 6     // 对异常1的处理
 7     System.out.print("出现了算术异常");
 8 } catch (Exception e) {
 9     // 对异常2的处理
10     // 以此类推还可以加各种异常的处理,由上图结构可知,Exception是运行时异常的父类,所以所有异常都能被exception接收,一般情况下如果没有对特定异常的特殊处理catch写exception就可以了
11     e.printStackTrace();// 打印异常的堆栈信息
12 } finally {
13     // 程序代码块 -- 异常处理结构最后处理的部分
14 }

  try 语句块:用于执行可能有异常的代码块。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。

  catch语句块:一个try catch结构中可以有多个catch,捕获不同的异常做不同的异常处理,没有特殊需求,一般用一个Exception就可以了

  异常捕获范围问题:多个catch的时候,所有捕获范围小的异常必须放在捕获范围大的异常之前,否则程序在编译时就会出现错误提示。参考异常结构图,例如上面的代码段,把 Exception 和 ArithmeticException 交换位置,Exception在前, 由异常结构图可知,Exception是ArithmeticException 的父类,所以有算术异常的时候,Exception也可以捕获该异常,后面添加 ArithmeticException 已经没有用了,故而会直接编译报错。

  finally语句块:一个try catch结构中finally可写可不写,有finally语句块的时候,表示不管是否有异常该代码块一定会被执行,一般常用于输入流、输出流关闭。

  注意:面试常被问的地方:如果在try里面有return,finally是否执行答:finally语句块依旧会被执行,在try语句块中的return之前执行

  以下4中特殊情况finally不会执行:

    • 在finally语句块中发生了异常
    • 在前面的代码中使用了System.exit()退出程序
    • 程序所在线程死亡
    • 关闭CPU

  b>.throws,throw

  某个方法可能会发生异常,但不想在当前方法中处理这个异常,则可以使用 throwsthrow 关键字在方法中抛出异常。

  throws关键字通常被应用在声明方法时,用来指定方法可能抛出的异常(多个异常可用逗号分隔 ),语法如下:

 1 public static void main(String[] args) {
 2     try{
 3         test();
 4     }catch(ArithmeticException e){
 5         System.out.print("test()方法抛出算术异常");
 6     }
 7 }
 8     
 9 public static void test() throws ArithmeticException{
10     int result = 3/0;
11 }

  使用throws 关键字将异常抛给上一级以后,如果不想处理该异常,可以继续向上抛出,如果main() throws Exception 就相当于交给JVM进行异常处理。

  throw 关键字通常用于方法体中,并且抛出一个异常对象程序执行到throw语句时立即终止,它后面的语句都不执行。

1 public static void main(String[] args) {
2    try {
3       throw new Exception("抛着玩的");
4     } catch (Exception e) {
5         e.printStackTrace();
6     }
7 }
程序运行结果:
java.lang.Exception: 抛着玩的
    at test.TestException2.main(TestException2.java:11)

  由于存在了throw关键字,本程序会手工抛出一个异常类的实例化对象,而此时程序必须使用 try...catch 语句进行处理,或者在方法上增加一个throws声明,否则程序会编译出错。

  throw 和 throws 的区别:

    throw:用户手工抛出异常类的实例化对象;

    throws:用于方法的声明上,表示此方法不处理异常,而将异常

  c>.自定义异常

  使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户只需继承Exception类即可自定义异常类。

  在程序中使用自定义异常类,大体可分为以下几个步骤。
  (1)创建自定义异常类。
  (2)在方法中通过throw关键字抛出异常对象。
  (3)如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
  (4)在出现异常方法的调用者中捕获并处理异常。

 1 public class MyException extends Exception { // 定义异常类
 2     public MyException(String errMessage){
 3         super(errMessage);
 4     }
 5 }
 6 
 7 public static int avg(int num1, int num2) throws MyException {
 8     if (num1 < 0 || num2 < 0) {
 9         throw new MyException("不可以使用负数");
10     }
11     if (num1 > 100 || num2 > 100) {
12         throw new MyException("数值太大了");
13     }
14     return (num1 + num2) / 2;
15 }
16 
17 public static void main(String[] args) {
18     try {
19         int result = avg(103, 150);
20         System.out.print(result);
21     } catch (MyException e) {
22         System.out.print(e);
23     }
24 }

运行结果:
  test.MyException: 数值太大了

3.常见异常类

  • NullPointerException   空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
  • ClassCastException    类型转换异常
  • ClassNotFoundException  未找到相应的类异常
  • ArithmeticException    算术异常
  • ArrayIndexOutOfBoundsException  数组索引越界异常
  • ArrayStoreException  数组中包含不兼容的值抛出的异常
  • SQLException   操作数据库异常类
  • NoSuchFieldException   字段未找到异常
  • NoSuchMethodException   方法未找到抛出的异常

  • NumberFormatException    字符串转换为数字抛出的异常
  • NegativeArraySizeException    数组长度为负异常
  • StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
  • IOException  操作输入流和输出流时可能出现的异常
  • IllegalArgumentException    非法参数异常
  • InstantiationException  当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
  • ArrayStoreException    数组中包含不兼容的值抛出的异常
  • SecurityException    安全性异常
  • EOFException      文件已结束异常
  • FileNotFoundException     文件未找到异常
  • NumberFormatException      字符串转换为数字抛出的异常
  • IllegalAccessException     不允许访问某类异常
原文地址:https://www.cnblogs.com/Jenny-sider/p/8330470.html