• [学习笔记]Java异常机制


    概述

    异常

    程序在执行时出现的不正常情况,是对问题的描写叙述。将问题进行对象的封装。

    Java中的异常,就是对不正常情况进行描写叙述后的对象体现。


    异常体系

    Throwable
        |--Error
        |--Exception
              |--RuntimeException
    • 当中Error类处理严重异常,一般不编写针对性的代码对其进行处理。
    • Exception类处理非严重异常,能够使用针对性的处理方式进行处理。

    不管Error或者Excption都具有一些共同的属性和方法,比方不正常情况的信息和引发原因等。


    异常类方法


    • getMessage()
      获取异常信息,返回字符串。

    • toString()
      获取异常类名和异常信息,返回字符串。
    • printStackTrace()
      获取异常类名和异常信息,以及异常出如今程序中的位置。直接打印,返回值void。
    • printStackTrace(PrintStream s)
      通经常使用该方法将异常内容保存在日志文件里,以便查阅。

    特点

    异常体系中全部的类以及建立的对象都具有可抛性,也就是说能够被throw和throwskeyword操作,仅仅有异常体系具备这个特点。


    throw和throws的使用方法

    • throw定义在方法内,用于产生异常对象。

    • throws定义在方法上,用于抛出方法内产生的异常类,抛出多个异经常使用逗号隔开。

    演示样例

    class Div {
    int div(int a, int b) throws Exception // 必须对其的调用进行捕获或声明以便抛出
    {
    return a / b;
    }
     
    int MultiEx(int a, int b) throws ArithmeticException, ArrayIndexOutOfBoundsException {
    int c = a / b;
    int[] arr = new int[a];
    System.out.println(arr[a]);
    return c;
    }
    }
     
    public class ExceptionDemo {
    public static void main(String[] args) // throws Exception
    {
    Div d = new Div();
    try {
    int x = d.div(2, 0);
    System.out.println("x = " + x);
    } catch (Exception e) {
    System.out.println("异常!

    ");

    System.out.println(e.getMessage()); // 异常信息
    System.out.println(e.toString()); // 异常名称:异常信息
    e.printStackTrace(); // 异常名称:异常信息
    // 异常出现的位置
    }
    System.out.println("----------------");
    try {
    int x = d.MultiEx(4, 1);
    System.out.println("x = " + x);
    } catch (ArithmeticException e) {
    System.out.println("除数不能为0!");
    System.out.println(e.toString());
    } catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组下标越界!

    ");

    System.out.println(e.toString());
    } catch (Exception e) {
    System.out.println(e.toString());
    }
    System.out.println("----------------");
    }
    }

    执行结果

    异常!

    / by zero
    java.lang.ArithmeticException : / by zero
    java.lang.ArithmeticException : / by zero
         at Div.div(ExceptionDemo.java:4)
         at ExceptionDemo.main(ExceptionDemo.java:21)
    ----------------
    数组下标越界。
    java.lang.ArrayIndexOutOfBoundsException : 4
    ----------------

    分层思想

    当捕获到异常,本功能处理不了时。能够继续在catch中抛出。
    try
    {
    throw new AException();
    }
    catch(AException e)
    {
    throw e;
    }
    假设该异常处理不了。但并不属于该功能出现的异常。为了进行模块式开发,减少耦合性,能够将异常转换后,再抛出和该功能相关的异常。

    或者异常能够处理,但须要将异常产生后和本功能相关的问题提供出去,抛出让调用者能够处理的异常和信息,也能够将捕获异常处理后转换新的异常抛出。

    所以异常发生不一定抛出原来的异常,也能够在本层处理后抛出上一层能够接受的异常。

    try
    {
    throw new AException();
    }
    catch(AException e)
    {
    //对AException处理。
    throw new BException;
    }

    异常处理方式

    1. 捕捉

    格式

    try{
         须要被检測的代码
    }
    catch(异常类 变量){
         对捕获到的异常进行处理。异常对象的常见操作:String getMessage()获取异常信息等。
         一定要定义详细的处理方法,不要简单一句e.printStackTrace(),也不要简单一句输出语句。一般使用错误日志进行保存。

    }
    finally{
         定义一定运行的代码。通经常使用于关闭资源。
    }

    有三种结合方式

    • try{}catch(){}
    • try{}catch(){}finally{}
    • try{}finally{}

    注意

    • finally中定义的一般是关闭资源码,由于资源必须释放。
    • 仅仅有在catch中使用了System.exit(0)方法时,不运行finally中的代码。


    2. 抛出

    使用throwskeyword将产生的异常抛出。交由调用者处理。

    3. 演示样例

    class Demo1 {
    void func() throws Exception {
    // 异常处理:抛出
    throw new Exception();
    }
    }
     
    class Demo2 {
    void func() {
    // 异常处理:捕捉
    try {
    throw new Exception();
    } catch (Exception e) {}
    }
    }
     
    class Demo3 {
    void func() throws Exception {
    try {
    throw new Exception();
    } catch (Exception e) {
    // 捕捉异常。假设无法处理,能够继续抛出e
    throw e;
    }
    }
    }
     
    class Demo4 {
    void func() {
    try {
    throw new Exception();
    } catch (Exception e1) {
    // 捕捉异常,假设无法处理。能够将异常e1转化成调用者可接受异常后抛出
    try {
    throw e1;
    } catch (Exception e2) {
    // 异常转换
    }
     
    }
    }
    }
     
    class Demo5 {
    void func() throws Exception {
    try {
    throw new Exception();
    } finally {
    // 关闭资源
    }
    }
    }

    4. 多异常的处理

    1. 声明异常时。建议声明更为详细的异常。这样处理能够做到更详细。

    2. 声明几个异常。就相应有几个catch块,不要定义多余的catch块。

    假设多个catch块中的异常出现继承关系,父类异常catch块放最后。


    5. 异常分类

    1. 编译时被检測异常(Exception类)
    • 该异常在编译时,假设没有处理(没抛出也没捕捉)。编译失败。该异常被标识。表示能够被处理。

    • 该异常必须进行异常处理(抛出或者捕捉)。
    2. 执行时异常(编译时不检測。RuntimeException类)
    • 编译时,不须要处理,编译器不检查。
    • 假设在函数内抛出该异常或其子类异常。函数上不须要声明。
      假设在函数上抛出该异常或其子类异常,调用者也不须要处理。
      由于这类异常一般无法正确继续程序。一旦出现,希望终止程序并由程序猿改动代码以解决该类异常。
    • 自己定义异常发生时,假设该异常无法继续程序执行,就让其继承RuntimeException。

    6. 异常处理原则

    • 当函数内部有throw抛出异常对象,并未进行try处理。必须在函数上声明,否则编译失败。

      RuntimeException及其子类除外。

    • 假设函数声明了异常。调用者须要进行处理。处理方式有两种。即捕捉和抛出。
    • 函数上声明异常。可以提高安全性。强制调用者进行处理。
    • 调用到抛出异常的功能时。抛出几个,就处理几个。出现一个try相应多个catch。当中父类的catch放最以下。


    自己定义异常

    依照Java的面向对象思想。将程序中出现的特有问题进行封装。

    用法

    定义继承Exception或者RuntimeException的异常类
    1. 为了让该自己定义类具有可抛性。

    2. 让该类具备操作异常的共性方法。

    3. 当要定义自己定义异常信息时,能够使用父类已经定义好的功能,异常信息传递给父类的构造函数。

    class MyException extends Exception
    {
    MyException(String msg)
    {
    super(msg);
    }
    }

    自己定义异常的优点

    1. 将问题进行封装。
    2. 将正常流程代码和问题处理代码相分离,方便阅读。

    自己定义异常在父子类方法重写中的情况

    1. 子类在重写父类时。假设父类的方法抛出异常,那么子类的重写方法,仅仅能抛出父类的异常或者该异常的子类。

    2. 假设父类方法抛出多异常,那么子类的重写方法。仅仅能抛出父类异常的子集。

    3. 假设父类或者接口方法中没有异常抛出。那么子类在重写方法时,也不能够抛出异常。假设子类方法发生异常,仅仅能在方法内部进行捕捉处理。

    演示样例
    /*
    * 自己定义异常继承体系
    * Exception
    * |--AException
    * | |--BException
    * |--CException
    */
    class AException extends Exception {}
     
    class BException extends AException {}
     
    class CException extends Exception {}
     
    class Father {
    void func() throws AException {}
    }
     
    class Son extends Father {
    void func() throws BException {
    // 仅仅能抛出AException或者AException的子类BException,不能抛出CException
    // 假设子类产生新异常CException。这里仅仅能try,不能抛出。
    }
    }

    自己定义异常演示样例

    class NegativeException extends Exception {
     
    private int value;
     
    NegativeException(String msg) {
    super(msg);
    }
     
    NegativeException(String msg, int value) {
    super(msg);
    this.value = value;
    }
     
    int getValue() {
    return value;
    }
    }
     
    class Demo {
    int customExc(int x) throws NegativeException // 函数内手动抛出非执行时异常。必须对其进行捕捉或声明抛出。
    {
    if (x < 0) throw new NegativeException("负数!", x);
    return x;
    }
     
    int runtimeExc(int x) // 函数内手动抛出RuntimeException异常或其子类异常,不须要对其进行捕捉或声明抛出。
    {
    if (x == 0) throw new ArithmeticException("数值为0!

    ");

    return x;
    }
     
    void checkString(String s) {
    if (s.equals("String"))
    // 避免空指针异常,应改动为:
    // if("String".equals(s))
    System.out.println("PASS!");
    else
    System.out.println("FAIL!");
    }
    }
     
    public class ExceptionCustom {
    public static void main(String[] args) // throws Exception
    {
    Demo d = new Demo();
     
    try {
    int x = d.customExc(-3);
    System.out.println("x = " + x);
    } catch (NegativeException e) {
    System.out.println(e.toString() + " 该数为:" + e.getValue());
    }
    System.out.println("-------------------");
    d.runtimeExc(0); // 算术异常(执行时),停止程序,须要程序猿改动代码。
    System.out.println("-------------------");
    d.checkString("String");
    d.checkString(null); // 空指针异常(执行时)。

    System.out.println("-------------------");
    }
    }

    自己定义异常实例

    // 员工使用电脑案例
    /**
    * 电脑死机异常
    */
    class CrashException extends Exception {
    CrashException(String msg) {
    super(msg);
    }
    }
     
    /**
    * 电脑烧毁异常
    */
    class BurnException extends Exception {
    BurnException(String msg) {
    super(msg);
    }
    }
     
    /**
    * 无法工作异常
    */
    class WorkException extends Exception {
    WorkException(String msg) {
    super(msg);
    }
    }
     
    class Computer {
    // 电脑状态,0电脑正常。1电脑死机。2电脑烧毁
    private int state = 0;
     
    public void run() throws CrashException, BurnException {
    if (state == 1) throw new CrashException("电脑崩溃了!");
    if (state == 2) throw new BurnException("电脑烧毁了!");
    System.out.println("电脑执行...");
    }
     
    public void reboot() {
    System.out.println("电脑重新启动...");
    state = 0;
    }
     
    public void setState(int state) {
    this.state = state;
    }
    }
     
    abstract class Employee {
    private String name;
     
    Employee(String name) {
    this.name = name;
    }
     
    abstract void work() throws WorkException;}
     
    class Staff extends Employee {
    private Computer com;
     
    Staff(String name) {
    super(name);
    com = new Computer();
    }
     
    public void work() throws WorkException {
    try {
    com.run();
    } catch (CrashException e) {
    // 假设电脑死机了。则重新启动电脑就可以
    System.out.println(e.toString());
    com.reboot();
    } catch (BurnException e) {
    // 假设电脑烧毁了。则向上级报告。抛出无法工作异常请求放假。
    throw new WorkException("无法继续工作! 原因:" + e.toString());
    }
    System.out.println("工作!");
    }
     
    public void computerStateChange(int state) {
    com.setState(state);
    }
    }
     
    public class ExceptionCase {
    public static void main(String[] args) {
    Staff s = new Staff("Jacob");
    // 分别针对不同的电脑状态,模拟工作情况
    for (int i = 0; i < 3; i++) {
    System.out.println("------------------情况" + i + ":------------------");
    // 更改员工电脑的状态
    s.computerStateChange(i);
    // 员工工作
    try {
    s.work();
    } catch (WorkException e) {
    System.out.println(e.toString() + " 放假!

    ");

    }
    }
    }
    }

    执行结果

    ------------------情况0:------------------
    电脑执行...
    工作!
    ------------------情况1:------------------
    CrashException: 电脑崩溃了。
    电脑重新启动...
    工作。
    ------------------情况2:------------------
    WorkException: 无法继续工作!
    原因:BurnException: 电脑烧毁了!
    放假。

  • 相关阅读:
    K近邻法
    决策树
    朴素贝叶斯
    Git学习笔记
    【原】maven web项目eclipse搭建
    三道面试题
    72-74 流的考点
    57-71 容器考点
    四 java web考点
    五 数据库考点
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7222259.html
Copyright © 2020-2023  润新知