【Java的学习之路】异常用不好,代码好不了

什么是异常?

异常(Exception)是在程序执行期间发生的问题或错误的信号。它表示程序运行过程中出现了一些不正常的情况,可能导致程序无法正常继续执行。

异常可以分为两类:Checked Exception(编译时异常)和 Unchecked Exception(运行时异常)。

  1. Checked Exception(编译时异常): 这类异常在代码编译阶段就会被检测到,程序员必须在代码中进行显式的处理或声明。通常是一些不可控的外部因素导致的异常,比如文件不存在、网络连接中断、数据库访问失败等。在Java中,所有继承自 Exception 类,但不继承自 RuntimeException 的异常都属于 Checked Exception。
  2. Unchecked Exception(运行时异常): 这类异常通常是由程序执行时的错误或逻辑错误导致的,是一种在运行时才能被检测到的异常。与 Checked Exception 不同,程序员在代码中不是强制性地要求处理或声明这类异常。在Java中,所有继承自 RuntimeException 的异常都属于 Unchecked Exception。

Throwable 类概述

Throwable 类是 Java 异常体系的根类,它是所有异常(Exception)和错误(Error)的基类。

继承关系:

php 复制代码
Throwable
--| Exception      // 异常,可被处理,程序还有拯救的可能性
--| Error          // 错误,通常表示系统级别的问题,GG思密达

常用构造方法:

  1. Throwable();:无参数构造方法,创建一个 Throwable 对象,其中存储的异常或错误信息为 null。
  2. Throwable(String message);:带有消息参数的构造方法,创建一个 Throwable 对象,其中存储的异常或错误信息为指定的 message。

常用方法:

  1. String getMessage();:获取 Throwable 对象中存储的异常或错误信息。
  2. String toString();:返回当前异常或错误的简要描述。
  3. void printStackTrace();:展示错误的前因后果,以红色字体显示在控制台上。

Error 和 Exception 的区别

Exception 表示可处理的异常情况,程序员有能力通过捕获和处理它来进行优雅的错误处理;

Error 表示不可处理的错误,通常由系统级问题引起,只能尽力避免。

如何处理异常?

1、捕获异常: 使用 try-catch 语句块捕获可能抛出异常的代码段,以便在异常发生时执行相应的处理逻辑。

csharp 复制代码
try {
    // 可能抛出异常的代码
} catch (ExceptionType e) {
    // 处理异常的代码
}

2、多重捕获: 可以使用多个 catch 块来捕获不同类型的异常,以执行不同的处理逻辑。

csharp 复制代码
try {
    // 可能抛出异常的代码
} catch (ExceptionType1 e1) {
    // 处理第一种异常的代码
} catch (ExceptionType2 e2) {
    // 处理第二种异常的代码
}

3、finally 块: finally 块中的代码总是会在 try 块执行后不论是否发生异常都会被执行,用于释放资源或执行必须完成的操作。

php 复制代码
try {
    // 可能抛出异常的代码
} catch (Exception e) {
    // 处理异常的代码
} finally {
    // 总是执行的代码块,用于清理资源等
}

4、抛出异常: 使用 throw 关键字手动抛出异常,将异常传播给上层调用者。

arduino 复制代码
if (condition) {
    throw new CustomException("Error message");
}

5、自定义异常: 可以创建自定义异常类,继承自 Exception 或其子类,以满足特定应用场景的异常需求。

scala 复制代码
public class CustomException extends Exception {
    // 构造方法等...
}

6、try-with-resources: 在 Java 7 及以上版本,可以使用 try-with-resources 语句来自动关闭实现 AutoCloseable 接口的资源,如文件、网络连接等。

java 复制代码
try (ResourceType resource = new ResourceType()) {
    // 使用资源的代码
} catch (Exception e) {
    // 处理异常的代码
}

7、throws: 是 Java 中用于在方法签名中声明可能抛出的受检查异常的关键字。当一个方法可能抛出某些异常,但不进行处理时,可以使用 throws 关键字在方法声明中指定这些异常。

java 复制代码
ReturnType methodName(ParameterList) throws ExceptionType1, ExceptionType2, ... {
    // 方法体
}

异常是如何产生的?(从堆栈层面看)

  1. 方法调用: 当一个方法被调用时,Java 虚拟机(JVM)会在调用栈中为该方法创建一个新的帧(frame)。每个帧包含了该方法的局部变量、操作数栈和方法返回地址等信息。
  2. 异常抛出: 在方法执行过程中,如果发生了异常情况(比如除零错误、空指针引用等),该异常将被封装成一个异常对象,并在当前方法中抛出。
  3. 异常传播: 抛出的异常会沿着调用栈向上传播,寻找能够处理这个异常的代码块。如果在当前方法中没有合适的异常处理机制,异常会沿着调用栈向上一层一层传递,直到找到合适的异常处理代码。
  4. 异常处理: 当异常到达调用栈的某一层,并且找到了能够处理该异常的代码块(比如使用 try-catch 块),异常将在这一层被捕获,并且执行相应的处理代码。
  5. 调用栈展开: 异常处理完成后,程序将从异常发生的地方继续执行,调用栈将会逐层展开,回到异常发生的地方之后的代码继续执行。

为什么不使用"大"异常(Exception)

你是否一直以来都有一个疑问,既然Exception能包括一切异常为什么不直接使用Exception呢?事实证明,在日常开发中我经常遇事不决就Exception,但是这种方式是错误的(反面教材哈)。

  1. 失去精确性: Exception 是所有异常类的父类,声明 throws Exception 无法准确指定方法可能抛出的具体异常类型,丧失了异常信息的精确性。
  2. 不利于调试: 使用 throws Exception 可能会隐藏真正的问题,不清晰地指明方法可能发生的异常类型,使得调试过程变得困难。
  3. 不符合规范: Java 编码规范推荐明确指定方法可能抛出的异常类型,以提高代码的清晰性和可读性。
  4. 不方便处理: 调用者在处理异常时,更希望知道具体的异常类型,以便根据不同的异常情况采取不同的处理策略。使用 throws Exception 使得异常处理变得笼统和不灵活。

日常开发中常见的异常有哪些?

编译时异常(Checked Exceptions):

这些异常在编写代码时必须进行处理,要么使用 try-catch 块捕获,要么在方法签名中使用 throws 关键字声明。如果不处理,编译器会报错。

IOException - 输入输出异常

ini 复制代码
try {
    FileReader fileReader = new FileReader("nonexistentfile.txt");
} catch (IOException e) {
    e.printStackTrace();
}

SQLException - SQL异常

ini 复制代码
try {
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password");
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM nonexistingtable");
} catch (SQLException e) {
    e.printStackTrace();
}

ClassNotFoundException - 类未找到异常

ini 复制代码
try {
    Class<?> clazz = Class.forName("com.example.NonExistingClass");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

运行时异常(Unchecked/Runtime Exceptions):

这些异常在编写代码时不强制要求进行处理,可以不使用 try-catch 或者 throws 进行异常处理。这些异常通常由于编程错误引起,而不是外部因素。

NullPointerException - 空指针异常

ini 复制代码
String str = null;
int length = str.length(); // 这里会抛出 NullPointerException

ArrayIndexOutOfBoundsException - 数组越界异常

ini 复制代码
int[] arr = {1, 2, 3};
int value = arr[5]; // 这里会抛出 ArrayIndexOutOfBoundsException

IndexOutOfBoundsException - 索引越界异常

ini 复制代码
List<String> list = new ArrayList<>();
String value = list.get(10); // 这里会抛出 IndexOutOfBoundsException

ArithmeticException - 算术异常

ini 复制代码
int result = 10 / 0; // 这里会抛出 ArithmeticException

NumberFormatException - 数字格式异常

ini 复制代码
String str = "abc";
int value = Integer.parseInt(str); // 这里会抛出 NumberFormatException

ClassCastException - 类型转换异常

ini 复制代码
Object obj = "Hello";
Integer num = (Integer) obj; // 这里会抛出 ClassCastException

ConcurrentModificationException - 并发修改异常

ini 复制代码
List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
list.add("New Element"); // 这里会抛出 ConcurrentModificationException

NoSuchElementException - 无此元素异常

ini 复制代码
List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
String value = iterator.next(); // 这里会抛出 NoSuchElementException

总结

一定要多思考,如果人永远待在舒适圈的话,人永远不会成长。共勉

觉得作者写的不错的,值得你们借鉴的话,就请点一个免费的赞吧!这个对我来说真的很重要。૮(˶ᵔ ᵕ ᵔ˶)ა

相关推荐
m0_74824517几秒前
Web第一次作业
java
小码的头发丝、几秒前
Java进阶学习笔记|面向对象
java·笔记·学习
m0_548514774 分钟前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
坊钰32 分钟前
【Java 数据结构】移除链表元素
java·开发语言·数据结构·学习·链表
chenziang137 分钟前
leetcode hot100 LRU缓存
java·开发语言
会说法语的猪43 分钟前
springboot实现图片上传、下载功能
java·spring boot·后端
码农老起43 分钟前
IntelliJ IDEA 基本使用教程及Spring Boot项目搭建实战
java·ide·intellij-idea
m0_748239831 小时前
基于web的音乐网站(Java+SpringBoot+Mysql)
java·前端·spring boot
时雨h1 小时前
RuoYi-ue前端分离版部署流程
java·开发语言·前端