Java异常

 

1、异常分类

检查性异常

最具代表的检查性异常是用户的错误或问题引起的异常,这是程序员无法预见的,这些异常在编译时不能简单地被忽略。比如用户要打开一个不存在的文件时,异常就发生了。

运行时异常

运行时异常是可能被程序员避免的异常,可以在编译时忽略。

错误

错误不是异常,而是脱离程序员控制的问题,错误在代码中常常被忽略。

2、异常体系结构

  • Java把异常当作一个对象处理,并定义一个基类java.Lang.Throwable作为所有异常的超类

  • Java异常体系结构图如下:

  • Error

    • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编译者所做的操作无关

    • 错误发生时,Java虚拟机一般会选择线程终止

  • Exception

    • 运行时的这些异常(RuntimeException)一般是由程序逻辑错误引起的,可以选择捕获处理也可以选择不处理

    • 通常情况下,Exception是可以被程序处理的,并且程序中应尽可能的去处理这些异常

3、捕获和抛出异常

捕获异常

这些运行期异常,Java虚拟机可以自动帮我们捕获,但是会终止线程,如果我们自己捕获并处理的话,程序不会终止,可以继续运行。

  • try:监控区域,存放可能会出现异常的代码块

  • catch:捕获异常,存放处理异常的代码块

    //语法
    catch(异常类型 参数名){}
    • 如果程序存在多个异常,也可以捕获多个异常,但是要注意层级关系:

      异常类型1的处理范围 < 异常类型2的处理范围 < 异常类型3的处理范围,Throwable的处理范围最大

    //语法
    catch(异常类型1 参数名){
       
    }catch(异常类型2 参数名){
       
    }catch(异常类型3 参数名){
       
    }
  • finally:处理善后工作,不管程序有没有出现异常,都会走finally,一般在关闭键盘交互、IO流、线程的代码会放在finally中

//不处理异常
public class Test {
   public static void main(String[] args) {
       int a = 10;
       int b = 0;
       int c = a/b;
       
       //不处理异常时,程序报错:java.lang.ArithmeticException: / by zero
       System.out.println(c);
  }
}

//捕获异常
public class Test {
   public static void main(String[] args) {
       int a = 10;
       int b = 0;
       int c = 0;

       try {
           c = a/b;
      } catch (ArithmeticException e) {
           System.out.println("出现算术异常-->除数为0");
      } finally {
           System.out.println("finally");
      }

       /*
       捕获异常,输出结果为:
      出现算术异常-->除数为0
      finally
      a / b = 0
        */
       System.out.println("a / b = " + c);
  }
}

抛出异常

  • 如果这个方法处理不了这个异常,就抛出,在调用这个方法的地方捕获处理这个异常或再次进行抛出

  • throw:用在方法体里

//抛异常
public static void division(int a,int b){
   if(b == 0){
       throw new ArithmeticException();
  }
   System.out.println(a/b);
}
  • throws:用在方法上

//抛异常
public void division(int a,int b) throws ArithmeticException{
   System.out.println(a/b);
}

4、自定义异常

  • 需要继承Exception类

步骤

  1. 创建自定义异常类

    public class MyException extends Exception {

       private String message;

       public MyException(String message){
           this.message = message;
      }

       @Override
       public String toString() {
           return "MyException{" + message +'}';
      }
    }
  2. 在方法中通过throw关键字抛出自定义异常对象

    public void division(int a,String message) throws MyException{
       if (a < 0) {
           throw new MyException(message);
      }
    }
  3. 如果在当前抛出异常的方法中处理异常

    • 可以使用try-catch语句捕获并处理

      public void division(int a,String message){
         if (a < 0) {
             try {
                 throw new MyException(message);
            } catch (MyException e) {
                 e.printStackTrace();
            }
        }
      }
    • 否则通过throws指明抛出异常,进行下一步操作

      public void division(int a,String message) throws MyException{
         if (a < 0) {
             throw new MyException(message);
        }
      }
  4. 在出现异常方法的调用者中捕获并处理异常

    try {
       new Test().division(-1,"出现算术异常-->除数为0");
    } catch (MyException e) {
       System.out.println(e);
    }

5、总结

  • 处理程序异常时,采用逻辑去合理规避同时辅助try-catch处理

  • 在多重catch块后面,可以加一个catch(Exception e)来处理可能会遗漏的异常

  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常

  • 尽量去处理异常,切忌只是简单地调用e.printStackTrace()去打印输出

  • 具体如何处理异常,要根据不同的业务需求和异常类型来决定

  • 尽量添加finally块去释放占有的资源

笔记内容均为自己看大神【狂神说Java】的视频整理的,给狂神点赞

狂神视频链接

原文地址:https://www.cnblogs.com/LittleSkinny/p/12785399.html