Java基础篇--错误处理机制

尽管人人希望自己身体健康,处理的事情都能顺利进行,但在实际生活中总会遇到各种状况,比如感冒发烧,工作时电脑蓝屏、死机等。同样,在程序运行的过程中,也会发生各种非正常状况,例如,程序运行时磁盘空间不足、网络连接中断、被装载的类不存在等。针对这种情况, Java语言引入了异常,以异常类的形式对这些非正常情况进行封装,通过错误处理机制对程序运行时发生的各种问题进行处理。

Java的错误处理机制是通过异常(Exception)来实现的。异常是在程序执行过程中出现的问题或错误的一种表示,它可以帮助我们识别和处理程序中的异常情况,从而保证程序的稳定性和可靠性。

异常类层次结构:

Java中的异常被组织成一个类层次结构。所有的异常都是Throwable类的子类,Throwable又分为两个子类:Error(错误类)和Exception(异常类)。其中,Error表示严重的系统级问题,通常是由虚拟机或底层资源引起的,例如内存溢出(OutOfMemoryError)。而Exception则表示可以被捕获和处理的异常情况,包括检查异常和运行时异常。

在Exception(异常类)类的众多子类中有一个特殊的子类—RuntimeException类,RuntimeException类及其子类用于表示运行时异常。 Exception类的其他子类都用于表示编译时异常。Java提供了大量的异常类,这些类都继承自java.lang.Throwable类。接下来通过一张图展示Throwable类的继承体系。

Java基础篇--错误处理机制_第1张图片

Throwable类中的常用方法如下表。

方法声明

功能描述

String getMessage()

返回异常的消息字符串 

String toString()

返回异常的简单信息描述

void printStackTrace()

获取异常类名和异常信息,以及异常出现在程序中的位置,

把信息输出在控制台。

检查异常:

这些异常是在编译时强制检查的异常。它们通常涉及到外部资源的操作,如文件I/O、网络连接等。开发者必须显式地处理或声明抛出这些异常。通过捕获和处理检查异常,可以使代码更加健壮,防止未处理异常导致程序崩溃或不可预测的结果。开发者需要使用 try-catch 块来捕获这些异常,并进行相应的处理。

try…catch具体语法格式如下:

try {
    // 可能引发异常的代码块
} catch (异常类型1 异常变量1) {
    // 处理异常类型1的情况
} catch (异常类型2 异常变量2) {
    // 处理异常类型2的情况
} catch (异常类型3 异常变量3) {
    // 处理异常类型3的情况
}

注意:catch代码块需要一个参数指明它所能够接收的异常类型,这个参数的类型必须是Exception类或其子类。 

运行时异常:

这些异常是不需要显式处理的异常,也不需要在方法签名中声明抛出。它们主要包括空指针引用(NullPointerException)、数组下标越界(ArrayIndexOutOfBoundsException)、类型转换错误(ClassCastException)等。运行时异常通常由程序逻辑错误导致,因此应该通过改进代码逻辑来预防发生这些异常。

下面是一个使用 try-catch 语句模仿数组下标越界的代码示例: 

public class myClass {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[4]); // 数组越界,会引发 ArrayIndexOutOfBoundsException 异常
        } catch (Exception e) {
            System.out.println("捕获到异常:" + e);//输出:捕获到异常:java.lang.ArrayIndexOutOfBoundsException: 4
        }
    }
}

异常处理语句:

Java提供了try-catch-finally的异常处理语句来捕获异常并进行相应的处理。在try块中编写可能会抛出异常的代码,如果发生了对应的异常,就会跳转到与之匹配的catch块中进行处理。catch块可以捕获特定类型的异常,也可以使用多个catch块按顺序处理不同类型的异常。finally块用于定义无论是否发生异常都要执行的代码,例如释放资源、关闭文件等。无论是否有异常发生,finally块中的代码都会执行。这样可以进行必要的清理工作,避免资源泄漏等问题。

注意:finally中的代码块在一种情况下是不会执行的,那就是在try...catch中执行了System.exit(0)语句。System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了。

下面是一个使用 try-catch-finally 异常处理语句的代码示例:

public class myClass {
    public static void main(String[] args) {
        try {
            int result = divideNumbers(10, 0); // 调用自定义方法,可能触发 ArithmeticException 异常
            System.out.println("结果:" + result);
        } catch (ArithmeticException e) {
            System.out.println("捕获到异常:" + e);
        } finally {
            System.out.println("无论是否发生异常,finally 块中的代码都会执行");
        }

        System.out.println("try-catch-finally 语句块之外的代码");
    }

    public static int divideNumbers(int a, int b) {
        return a / b; // 若除数为 0,则会触发 ArithmeticException 异常
    }
}

运行结果:

捕获到异常:java.lang.ArithmeticException: / by zero
无论是否发生异常,finally 块中的代码都会执行
try-catch-finally 语句块之外的代码

抛出异常:

在方法中,我们可以使用throw关键字主动抛出异常。通过throw语句,我们可以在任何需要的地方抛出异常,并将其传递给上层调用者来处理。抛出异常的过程中,当前方法的执行将被中断,然后异常被传递给调用堆栈中的上一级调用方法。

throws关键字声明抛出异常的语法格式如下:

修饰符 返回类型 方法名(参数列表) throws 异常类型1, 异常类型2, ... {
    // 方法体
}

其中:

  • 修饰符:表示方法的可见性和其他修饰符(例如 public、private、static 等)。
  • 返回类型:表示方法返回值的类型。
  • 方法名:表示方法的名称。
  • 参数列表:表示方法接收的参数。
  • 异常类型1, 异常类型2, ...:表示方法可能抛出的异常类型。多个异常类型之间使用逗号分隔。

下面是一个使用 throw 关键字的代码示例:

public class myClass {
    public static void main(String[] args) {
        try {
            int result = divideNumbers(10, 1); // 调用自定义方法,可能触发 ArithmeticException 异常
            System.out.println("结果:" + result);
        } catch (ArithmeticException e) {
            System.out.println("捕获到异常:" + e);//输出:捕获到异常:java.lang.ArithmeticException: / by zero
        } finally {
            System.out.println("无论是否发生异常,finally 块中的代码都会执行");//输出:无论是否发生异常,finally 块中的代码都会执行
        }

        System.out.println("try-catch-finally 语句块之外的代码");
    }

    public static int divideNumbers(int a, int b) throws ArithmeticException{
        if (b == 0) {
            throw new ArithmeticException("除数不能为零"); // 抛出 ArithmeticException 异常对象
        } else {
            int result = a / b;
            System.out.println("结果:" + result);
        }
        return a;
    }
}

运行结果:

捕获到异常:java.lang.ArithmeticException: 除数不能为零
无论是否发生异常,finally 块中的代码都会执行
try-catch-finally 语句块之外的代码

自定义异常:

除了Java内置的异常类,开发者还可以根据需要自定义异常类。自定义异常类需要继承Exception或其子类,并根据具体需求添加自己所需的字段和方法。自定义异常可以更好地满足业务需求,提供更准确的异常信息和处理方式。

你可能感兴趣的:(Java进阶篇,java,开发语言)