一篇文章详解Java异常处理

 更新时间:2023年12月18日 11:58:27   作者:cccc楚染rrrr  
异常处理是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件),这篇文章主要给大家介绍了关于Java异常处理的相关资料,需要的朋友可以参考下

Java异常的三种分类

  1. 受检异常(Checked Exceptions):最具代表性的是用户错误和问题引起的异常,程序员无法遇见,这些异常在编译时强制要求进行处理,比如打开一个不存在的文件。如果一个方法可能会引发受检异常,要么在方法签名中使用throws子句声明,要么使用try-catch块捕获并处理这些异常。例如,IOException就是一个受检异常,它需要在代码中进行显式处理。
  2. 运行时异常(Runtime Exceptions):这些异常是RuntimeException类及其子类的实例。与受检异常不同,编译时会被忽略,运行时异常不需要显式地捕获或声明。常见的运行时异常包括NullPointerException、ArrayIndexOutOfBoundsException和ArithmeticException等。
  3. 错误(Errors):错误通常指示了严重的问题,大多数情况下是程序无法处理的。与异常不同,错误通常不应该被捕获和处理。常见的错误包括StackOverflowError和OutOfMemoryError等。

异常体系结构

Java的异常体系结构是基于Throwable类的,java.lang.Throwable作为所有异常的超类

Error

Error类是Java编程语言中表示严重问题的基类之一。

在Java中,Error对象表示的是系统级的错误和运行时环境的问题,通常由Java虚拟机(JVM)生成和抛出。

与一般的异常不同,Error及其子类通常表示虚拟机自身的问题,而不是应用程序的问题。

一些常见的Error子类包括:

  • OutOfMemoryError:当JVM无法再分配内存时抛出,表示内存耗尽。
  • StackOverflowError:当方法调用的层级太深,导致栈空间耗尽时抛出。
  • NoClassDefFoundError:当JVM或ClassLoader无法找到所需的类定义时抛出。
  • InternalError:表示JVM内部发生了严重错误。

Exception

Exception类是Java编程语言中表示一般意外情况或错误的基类之一。

在Java中,Exception及其子类通常用于表示程序运行过程中可能发生的各种异常情况。

Exception类的直接子类主要分为两种:

  • Checked Exception:这些异常必须在代码中进行处理,要么通过try-catch块捕获和处理,要么通过throws子句声明向上传播。
  • RuntimeException:这些异常通常是由程序错误引起的,不要求在代码中强制处理。

一些常见的 Checked Exception:

  1. IOException:用于表示输入输出操作中可能发生的异常情况,如文件未找到、文件权限问题等。
  2. SQLException:用于表示与数据库访问相关的异常,例如连接问题、查询问题等。
  3. ClassNotFoundException:用于表示在运行时找不到特定类的异常。
  4. FileNotFoundException:指示尝试打开指定文件名的文件失败。
  5. ParseException:用于表示解析操作中可能发生的异常,例如日期解析错误。
  6. NoSuchMethodException:指示尝试访问不存在的方法时发生的异常。

一些常见的 RuntimeException:

  1. NullPointerException:当应用程序试图在要求使用对象的地方使用 null 时,抛出该异常。
  2. ArrayIndexOutOfBoundsException:用于指示数组索引超出范围。
  3. ArithmeticException:表示在算术运算中发生的异常情况,例如除以零。
  4. IllegalArgumentException:指示向方法传递了一个不合法或不正确的参数。
  5. IllegalStateException:表示对象的状态不适合请求的操作。
  6. ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常。

异常处理机制

1、try-catch块:try 用于包裹可能会引发异常的代码块,catch 用于捕获并处理特定类型的异常。如果 try 块中的代码引发了异常,Java 将会跳到匹配的 catch 块中执行相应的处理代码。

try {  
    // 可能引发异常的代码  
} catch (ExceptionType e) {  
    // 处理异常的代码  
}  

2、finally块:finally 块中的代码总是会被执行,无论是否发生异常。通常用于确保资源的释放,如关闭文件或网络连接。

try {  
    // 可能引发异常的代码  
} catch (ExceptionType e) {  
    // 处理异常的代码  
} finally {  
    // 无论是否发生异常都会执行的代码  
}  

3、throws关键字:throws 用于在方法声明中指定可能会抛出的异常,将异常的处理责任交给调用者。这就是告诉调用者,调用这个方法时,需要考虑到可能会抛出的异常情况。

void someMethod() throws SomeException {  
    // 方法可能抛出 SomeException  
}  
void readFile() throws IOException {  
    // 读取文件的代码  
}  

在这个例子中,readFile 方法声明了可能会抛出 IOException 异常。当其他代码调用 readFile 方法时,调用者需要考虑到可能会出现 IOException 异常的情况。

4、throw关键字:throw 用于手动抛出一个异常。这意味着当程序执行到 throw 语句时,会创建一个异常对象并将其抛出。这个异常可以是 Java 标准库中已经定义好的异常类型,也可以是你自己定义的异常类型。

if (someCondition) {  
    throw new SomeException("Error message");  
}  

举个例子,假设你正在编写一个函数,需要检查传入的参数是否满足某些条件,如果条件不满足,你可以使用 throw 抛出一个异常来中断程序的执行并给出相应的提示或错误信息。

void checkAge(int age) {  
    if (age < 0) {  
        throw new IllegalArgumentException("Age cannot be negative");  
    }  
}  

在这个例子中,如果传入的年龄是负数,throw 语句将会创建一个 IllegalArgumentException 异常对象并将其抛出。

5、自定义异常:可以通过扩展 Exception 类或其子类来创建自定义异常类,以便应用程序可以根据特定的需求创建和使用异常类型。

如果不加throws MyException会报错,这是因为:在Java中,如果一个方法可能抛出已检查异常(checked exception),但没有使用try-catch块捕获该异常,也没有使用throws子句将该异常传播出去,编译器会报错。

几种异常处理方式的区别:

  • throw 用于手动抛出异常,throws 用于声明可能会抛出的异常类型,而 try-catch 用于实际处理异常情况。
  • throw 和 try-catch 是用于实际处理异常的,而 throws 是在方法声明中指明可能会抛出的异常类型。

举例:

import java.io.BufferedReader;  
import java.io.FileReader;  
import java.io.IOException;  
  
public class FileHandlingExample {  
    public static void main(String[] args) {  
        BufferedReader reader = null;  
        try {  
            reader = new BufferedReader(new FileReader("example.txt"));  
            String line = reader.readLine();  
            int number = Integer.parseInt(line);  
            System.out.println("Read number: " + number);  
        } catch (FileNotFoundException e) {  
            System.err.println("File not found: " + e.getMessage());  
        } catch (NumberFormatException e) {  
            System.err.println("Invalid number format: " + e.getMessage());  
        } catch (IOException e) {  
            System.err.println("IOException: " + e.getMessage());  
        } finally {  
            try {  
                if (reader != null) {  
                    reader.close();  
                }  
            } catch (IOException e) {  
                System.err.println("Error while closing the reader: " + e.getMessage());  
            }  
        }  
    }  
}  

在这个例子中,我们尝试打开一个文件并读取其中的内容。在 try 块中,我们打开文件并尝试读取文件中的一行内容,并将其转换为整数。在 catch 块中,我们分别捕获了 FileNotFoundException(文件未找到)、NumberFormatException(无效的数字格式)和 IOException(输入输出异常)。

finally 块中,我们确保关闭了文件读取器,即使在 trycatch 块中发生了异常,也会执行这一步。这是非常重要的,因为它确保资源得到了正确的释放。

Java 编译器会按照 catch 块的顺序来匹配异常,而一旦找到了匹配的 catch 块,后续的 catch 块将不再执行。 因此,如果将最一般的异常类型放在最前面,那么可能会导致后续的 catch 块永远无法执行。

在前面提供的示例代码中,我们先捕获了 FileNotFoundException,然后是 NumberFormatException,最后是 IOException。这是符合最佳实践的顺序。

如果按照相反的顺序,即先捕获 IOException,然后是 NumberFormatException,最后是 FileNotFoundException,那么由于 IOExceptionFileNotFoundExceptionNumberFormatException 的父类,IOException 的 catch 块将会捕获到所有这些异常,而后续的 catch 块将无法执行。

因此,捕获异常时应该遵循从最具体的异常类型到最一般的异常类型的顺序,以确保程序能够按预期进行异常处理。

书写异常处理语句的快捷键:ctrl+alt(option)+T

手动结束程序语句:

实际使用中的经验总结:

  1. 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  2. 在多重catch块后面,可以加上一个catch(Exception)来处理可能会被遗漏的异常
  3. 对于不确定的代码,也可以加上try-catch处理异常
  4. 尽量去处理异常,切忌仅使用printStackTrace()打印输出
  5. 具体处理异常,根据业务需求和异常类型的不同决定
  6. 尽量添加finally释放占用的资源(IO、Scanner)

总结

到此这篇关于一篇文章详解Java异常处理的文章就介绍到这了,更多相关Java异常处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 类似微信说话功能的录音处理代码分享

    类似微信说话功能的录音处理代码分享

    这篇文章主要介绍了类似微信中说话功能的录音处理代码,需要大家自己加UI界面,大家参考使用吧
    2014-01-01
  • SpringMVC使用ResponseEntity实现文件上传下载

    SpringMVC使用ResponseEntity实现文件上传下载

    这篇文章主要为大家介绍了SpringMVC使用ResponseEntity实现文件上传下载,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • springsecurity6配置自定义路径身份认证的实现

    springsecurity6配置自定义路径身份认证的实现

    本文主要介绍了springsecurity6配置自定义路径身份认证的实现,通过使用自定义的AuthorizationManager和MyService,可以实现更灵活的访问控制,感兴趣的可以了解一下
    2025-03-03
  • java批量修改文件后缀名方法总结

    java批量修改文件后缀名方法总结

    在本篇文章里小编给大家分享了关于java批量修改文件后缀名方法和相关知识点,有需要的朋友们学习下。
    2019-03-03
  • Java内存模型JMM详解

    Java内存模型JMM详解

    这篇文章主要介绍了Java内存模型JMM详解,涉及volatile和监视器锁,final字段,内存屏障等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java基于二维数组实现的数独问题示例

    Java基于二维数组实现的数独问题示例

    这篇文章主要介绍了Java基于二维数组实现的数独问题,涉及java针对数组的遍历、计算、转换等相关操作技巧,需要的朋友可以参考下
    2018-01-01
  • Spring Boot中使用 Spring Security 构建权限系统的示例代码

    Spring Boot中使用 Spring Security 构建权限系统的示例代码

    本篇文章主要介绍了Spring Boot中使用 Spring Security 构建权限系统的示例代码,具有一定的参考价值,有兴趣的可以了解一下
    2017-08-08
  • Shiro集成Spring之注解示例详解

    Shiro集成Spring之注解示例详解

    Shiro想必大家都知道了,是目前使用率要比spring security都要多的一个权限框架,下面这篇文章主要给大家介绍了关于Shiro集成Spring之注解的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-09-09
  • Java向上转型和向下转型的区别说明

    Java向上转型和向下转型的区别说明

    这篇文章主要介绍了Java向上转型和向下转型的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • 基于SpringBoot后端导出Excel文件的操作方法

    基于SpringBoot后端导出Excel文件的操作方法

    这篇文章给大家介绍了基于SpringBoot后端导出Excel文件的操作方法,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02

最新评论