10.20(异常总结)

发布时间 2023-10-20 15:17:52作者: 徐星凯

Java项目中常用的异常处理情况包括try-catch语句、throws关键字、自定义异常等。try-catch语句用于捕获和处理异常,可以有多个catch语句,需要注意顺序。throws关键字用于声明方法可能抛出的异常类型。自定义异常需要继承自Exception类或其子类。finally语句在异常处理中非常重要,可以确保必要的清理工作总是被执行。使用日志记录器可以更好地了解程序运行过程中出现的异常情况。避免使用过于复杂的嵌套try-catch结构,将可能出现异常的代码块拆分成独立的函数进行处理。

  1. 异常的概念

在Java中,异常(Exception)是指程序运行过程中发生的非正常情况,它会中断程序的正常运行。异常可以分为两大类:受检异常(Checked Exception)和非受检异常(Unchecked Exception)。受检异常需要在代码中显式地进行处理,否则编译器会报错;非受检异常则不需要显式处理,编译器不会报错,但建议进行适当的处理。

  1. try-catch语句

try-catch语句是Java中最常用的异常处理方式。它的基本结构如下

try {

    // 可能抛出异常的代码块

} catch (ExceptionType1 e1) {

    // 处理ExceptionType1类型的异常

} catch (ExceptionType2 e2) {

    // 处理ExceptionType2类型的异常

} finally {

    // 无论是否发生异常,都会执行的代码块

}

在try代码块中,我们可以放置可能抛出异常的代码。当这些代码运行时,如果发生了异常,那么程序会立即跳转到对应的catch代码块进行处理。如果没有发生异常,那么程序会继续执行后面的代码。finally代码块中的代码无论是否发生异常,都会被执行。通常我们会在finally代码块中关闭资源、释放锁等操作。

  1. throws关键字

throws关键字用于声明一个方法可能抛出的异常类型。当一个方法内部发生了异常,但是不想在方法内部进行处理时,可以使用throws关键字将异常抛给上层调用者处理。例如:

public void readFile(String fileName) throws FileNotFoundException {

    // 读取文件的代码

}

  1. throw关键字

throw关键字用于手动抛出一个异常。当我们需要在某些条件下强制抛出一个异常时,可以使用throw关键字。例如:

public void checkAge(int age) {

    if (age < 0) {

        throw new IllegalArgumentException("年龄不能为负数");

    }

}

  1. 自定义异常

除了Java内置的异常类型外,我们还可以根据实际需求自定义异常。自定义异常需要继承自Exception类或其子类。例如:

class MyException extends Exception {

    public MyException(String message) {

        super(message);

    }

}

  1. 多个catch语句的顺序问题

当一个try代码块中有多个catch语句时,需要注意它们的顺序。因为编译器会根据顺序来匹配异常类型,如果匹配到了相应的catch语句,那么程序会跳转到该catch代码块进行处理。因此,我们应该将最具体的异常类型放在前面,将最通用的异常类型放在后面。例如:

try {

    // 可能抛出异常的代码块

} catch (IOException e) { // 处理IO异常

} catch (NullPointerException e) { // 处理空指针异常,比IOException更具体

} catch (Exception e) { // 处理其他所有异常,最通用的catch语句应该放在最后面

} finally {

    // 无论是否发生异常,都会执行的代码块

}

  1. finally语句的重要性

finally语句在异常处理中非常重要。它可以确保一些必要的清理工作总是被执行,例如关闭文件、释放资源等。即使try代码块中的代码没有发生异常,或者发生了异常但没有被捕获和处理,finally代码块中的代码仍然会被执行。因此,我们应该养成在finally代码块中添加必要清理操作的习惯。

  1. 使用日志记录异常信息

为了更好地了解程序运行过程中出现的异常情况,我们可以使用日志记录器(如log4j、slf4j等)来记录异常信息。这样,当程序出现异常时,我们可以查看日志来定位问题所在。例如:

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

public class ExceptionDemo {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionDemo.class);

 

    public void readFile(String fileName) {

        try {

        // 读取文件的代码

    } catch (FileNotFoundException e) {

        logger.error("文件未找到", e); // 使用日志记录器记录异常信息和堆栈跟踪信息

    } finally {

        // 关闭资源的代码

    }

}

  1. 避免使用过于复杂的嵌套try-catch结构

虽然try-catch语句可以帮助我们捕获和处理异常,但是过度使用复杂的嵌套try-catch结构会让代码变得难以阅读和维护。因此,我们应该尽量避免使用过于复杂的嵌套try-catch结构,而是尽量将可能出现异常的代码块拆分成多个独立的函数,然后在每个函数中使用try-catch语句进行处理。这样可以让代码更加清晰和易于维护。