Java 每日一刊(第16期):异常机制

前言

这里是分享 Java 相关内容的专刊,每日一更。

本期将为大家带来以下内容:

  1. 异常处理
  2. 捕获与处理异常
  3. 自定义异常
  4. try-with-resources

异常处理

什么是异常

异常 是程序在运行时出现的意外情况或错误,它中断了程序的正常执行流程。换句话说,异常就是程序无法按预期执行时,由系统或程序员明确抛出的信号,表示程序遇到了某种问题。

在软件开发中,我们总是试图编写可靠的代码,但是不可避免地会遇到一些问题,比如:

  • 用户输入无效数据(如本该输入数字时输入了字母)。
  • 系统资源不可用(如文件找不到或数据库无法连接)。
  • 程序内部逻辑错误(如除以零、数组越界等)。

这些问题在运行时触发的情况被称为 异常,异常的本质就是程序运行时的非预期行为。

在 Java 中,当程序遇到错误时,会生成一个 异常对象,该对象封装了错误信息。然后,通过抛出这个异常对象,程序将异常信息传递给调用栈的上层方法,以便处理该错误。如果该异常没有被程序处理,最终会导致程序终止。

举个简单的例子:

int a = 10;
int b = 0;
int result = a / b;  // 此处会触发异常:ArithmeticException (除以零)

在上面的代码中,当 b 为 0 时,Java 将抛出一个 ArithmeticException(算术异常),因为除以零在数学上是未定义的。这种情况下,程序会中断,并输出异常的详细信息。

异常层次结构

在 Java 中,异常(Exception)是程序在运行时遇到问题时用来报告错误的机制。为了更好地管理这些错误,Java 使用了一个“异常层次结构”,把不同的异常分类。

           Throwable/      \Error    Exception/      \RuntimeException  CheckedException

Throwable:是 Java 中所有错误和异常的根类,分为两大子类:ErrorException

Error:表示无法恢复的严重错误,通常是 JVM 层面的问题,如内存溢出(OutOfMemoryError),程序不应该试图处理这些错误。

Exception:表示程序运行中的可预期问题,程序员可以捕捉并处理。分为:

  • RuntimeException(非受检异常):如 NullPointerExceptionIndexOutOfBoundsException 等。
  • Checked Exception(受检异常):如 IOExceptionSQLException 等。

Checked 异常与 Unchecked 异常

类别Checked Exception(受检异常)Unchecked Exception(非受检异常)
定义在编译时由编译器强制要求处理的异常。即运行时异常,编译器不要求强制处理。
继承关系继承自 Exception 类,**但不包括 **RuntimeException继承自 RuntimeException 类。
处理方式必须通过 throws 声明抛出,或使用 try-catch 块显式捕获。编译器不强制要求处理,程序可以选择捕获或忽略。
典型场景与外部资源交互时,可能发生不可避免的异常。通常由程序逻辑错误或编程不当导致。
常见示例IOException(文件或网络 I/O 错误)
SQLException(数据库操作异常)
NullPointerException(空指针异常)
ArrayIndexOutOfBoundsException(数组越界异常)
开发者处理需求调用方法时必须显式处理(捕获或抛出)。可以选择处理或忽略,程序运行时会抛出异常。
是否可预测通常可预测的异常,发生在程序运行时与外部资源交互的过程中。通常是不可预测的程序错误,往往是编程不当导致。
强制性是。必须处理或声明。否。编译时不会检查。

异常与错误

类别Exception(异常)Error(错误)
定义程序运行过程中可能发生的可预期问题,通常是程序或外部环境的异常情况。严重的、不可恢复的问题,通常是 JVM 层面的问题,无法通过程序处理。
继承关系继承自 Throwable 类,且进一步分为 Checked 和 Unchecked 异常。继承自 Throwable 类,通常不建议捕获或处理。
常见场景通常与外部资源交互时出现,如文件操作、数据库访问。通常由系统资源耗尽、内存溢出或 JVM 崩溃引发。
处理方式开发者可以通过 try-catch 块捕获并处理,或者声明抛出。程序一般不应捕获 Error,且大部分情况下无法恢复。
是否可恢复是。异常通常可以通过适当的处理机制进行恢复。否。错误通常无法恢复,意味着程序已经处于不可继续执行的状态。
是否可预测通常是可预测的,且在程序中可以预见并进行处理。不可预测的系统级问题,通常与 JVM 和硬件资源相关。
常见示例IOException(输入输出异常) SQLException(数据库异常)OutOfMemoryError(内存溢出)
StackOverflowError(栈溢出)
开发者处理需求必须通过异常处理机制处理或声明,编译器强制要求处理受检异常。一般不建议处理,且大多数情况下无法处理或恢复。

捕获与处理异常

try-catch

try-catch 是 Java 中处理异常的核心机制。try 块包含可能抛出异常的代码,而 catch 块用于捕获并处理该异常。

try {int result = 10 / 0;  // 抛出 ArithmeticException
} catch (ArithmeticException e) {System.out.println("发生了除以零错误: " + e.getMessage());
}

try 块:包含了可能会导致异常的代码。如果在 try 中发生异常,程序的执行将跳转到 catch

catch 块:用于捕获并处理异常。它可以包含多个 catch,以处理不同类型的异常。

finally

finally 块在异常处理结束后执行,无论是否发生异常,finally 中的代码都会执行。通常用于释放资源,如关闭文件、数据库连接等。

try {// 打开文件或数据库连接
} catch (IOException e) {System.out.println("文件处理出错: " + e.getMessage());
} finally {// 关闭文件或释放资源
}

如果 trycatch 块中有 return 语句,finally 块仍然会在 return 语句之前执行。即使方法已经准备返回结果,finally 依然会先执行,然后再返回结果。

例如:

public static int testFinally() {try {System.out.println("In try block");return 1;  // 尝试返回 1} catch (Exception e) {System.out.println("In catch block");return 2;  // 捕获异常时尝试返回 2} finally {System.out.println("In finally block");return 3;  // 覆盖前面的 return 语句,最终返回 3}
}public static void main(String[] args) {System.out.println(testFinally());
}

输出:

In try block
In finally block
3

在上面的例子中,try 块中的 return 1 尝试返回 1,但在执行 return 前,finally 块中的 return 3 覆盖了原本的返回值,最终返回了 3。这说明即使 trycatch 中有 returnfinally 依然会执行,且如果 finally 中也包含 return,它会覆盖之前的返回值。

多重异常捕获与处理

Java 支持为一个 try 块提供多个 catch 块,每个 catch 块处理一种特定类型的异常。多个 catch 允许开发者对不同的异常类型做出不同的处理。

try {// 代码可能抛出多个异常
} catch (IOException e) {System.out.println("IO 异常: " + e.getMessage());
} catch (SQLException e) {System.out.println("SQL 异常: " + e.getMessage());
}

多异常捕获

Java 7 引入了多异常捕获机制,允许在同一个 catch 块中处理多个异常类型:

catch (IOException | SQLException e) {System.out.println("发生异常: " + e.getMessage());
}

这不仅简化了代码,也减少了重复代码的编写,提高了可读性。

throw 关键字

throw 用来手动抛出一个异常。当你确定程序中某些地方会发生特定的错误时,可以用 throw 抛出相应的异常,通知调用者这里有问题需要处理。

使用方法:

throw new ExceptionType("异常描述");

ExceptionType 是异常的类型,比如 IllegalArgumentExceptionNullPointerException 等等。

"异常描述" 是你自己定义的错误信息,便于理解异常原因。

举个例子:

public class Example {public static void main(String[] args) {int age = -1;if (age < 0) {throw new IllegalArgumentException("年龄不能为负数");}}
}

这个例子中,如果 age 小于 0,就会抛出一个 IllegalArgumentException 异常,并显示错误信息 “年龄不能为负数”。

throws 关键字

throws 用在方法声明上,表示这个方法可能会抛出某种类型的异常。它告诉调用这个方法的代码:小心,这个方法可能会抛出异常,你要负责处理这个异常。

使用方法:

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

你可以在方法声明中列出可能抛出的异常类型,用逗号分隔。

如果一个方法抛出了异常而没有用 throws 关键字声明,编译器会报错。

举个例子:

public void readFile(String filePath) throws FileNotFoundException {File file = new File(filePath);if (!file.exists()) {throw new FileNotFoundException("文件未找到:" + filePath);}
}

这个方法 readFile 可能抛出 FileNotFoundException,所以在方法声明时使用 throws 来提醒调用者:你在调用我这个方法时要小心,有可能会出现文件找不到的异常。

throwthrows 的区别

throwthrows
定义用于显式抛出异常用于声明可能抛出的异常类型
使用位置在方法内部在方法签名中
语法throw new ExceptionType("message");public void methodName() throws ExceptionType
目的触发一个异常表示方法可能会抛出某些异常,调用者需处理
例子throw new IOException();public void readFile() throws IOException
处理直接抛出异常,程序可能终止允许调用者捕获并处理异常

自定义异常

自定义异常是在 Java 中自己定义的异常类,用于处理程序中特定的错误或业务逻辑。虽然 Java 已经内置了许多常见的异常类(如 NullPointerException, ArrayIndexOutOfBoundsException 等),但有时这些标准异常不能很好地描述你程序中的错误。此时,开发者可以通过创建自己的异常类,专门用来处理和表示特定的异常情况。

自定义异常类一般继承自 ExceptionRuntimeException。 例如:

public class CustomException extends Exception {public CustomException(String message) {super(message);}
}

try-with-resources

try-with-resources 是 Java 中用来自动关闭资源的一种机制。它特别适用于那些需要手动关闭的资源,比如文件、数据库连接、网络连接等。传统的 try-catch-finally 需要我们在 finally 代码块中显式地关闭这些资源,但 try-with-resources 可以帮我们自动完成这一过程,确保资源不会因为程序中的错误而忘记关闭。

具体怎么理解呢?

在程序中,像文件读写、数据库访问这类操作都需要 打开某些资源(例如打开文件或建立数据库连接),而这些资源一旦使用完毕就需要关闭。如果忘记关闭,可能会导致内存泄漏或资源耗尽。

传统做法中,我们会在 finally 块里手动关闭资源。比如:

BufferedReader br = null;
try {br = new BufferedReader(new FileReader("example.txt"));// 进行文件读取操作
} catch (IOException e) {e.printStackTrace();
} finally {if (br != null) {try {br.close();  // 手动关闭资源} catch (IOException e) {e.printStackTrace();}}
}

上面的代码中,finally 块确保了文件在使用完后一定会被关闭,即使中间发生了异常。但这样写比较繁琐。

使用 try-with-resources 怎么做?

使用 try-with-resources 后,代码变得更简单,因为资源会自动关闭:

try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {// 进行文件读取操作
} catch (IOException e) {e.printStackTrace();
}

优势:

  • 自动关闭资源:当 try 块结束时(无论是正常结束还是发生异常),BufferedReader 会自动关闭,无需手动在 finally 中编写 close()
  • 简化代码:减少了显式关闭资源的代码,避免写太多的 try-catch-finally,代码更加简洁明了。

使用 try-with-resources 的资源,必须实现 AutoCloseable 接口(很多常见的资源类,比如 BufferedReaderFileInputStream 等都已经实现了这个接口),这确保了它们具有 close() 方法可以被自动调用。

本期小知识

很多人认为 finally 块中的代码总是会执行,但有极少数情况会导致 finally 块不会执行:

  • JVM 关闭(例如调用 System.exit(0))。
  • 线程被强制中断或崩溃。
  • 程序因断电或操作系统强制关闭等外部因素终止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149542.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【十八】MySQL 8.0 新特性

MySQL 8.0 新特性 目录 MySQL 8.0 新特性 概述 简述 1、数据字典 2、原子数据定义语句 3、升级过程 4、会话重用 5、安全和账户管理 6、资源管理 7、表加密管理 8、InnoDB增强功能 9、字符集支持 10、增强JSON功能 11、数据类型的支持 12、查询的优化 13、公用…

【CSS】字体文本

color 颜色font-size 大小font-family 字体font-style 样式font-weight 加粗text-decoration 下划线text-shadow 阴影text-transform 大小写变换text-indent 缩进text-align 水平对齐 、vertical-align垂直对齐text-overflow 溢出word-wrap 换行word-break 截断white-space 空白…

最新绿豆影视系统 /反编译版源码/PC+WAP+APP端 /附搭建教程+软件

源码简介&#xff1a; 最新的绿豆影视系统5.1.8&#xff0c;这可是个反编译版的源码哦&#xff01;它不仅支持PC端、WAP端&#xff0c;还有APP端&#xff0c;一应俱全。而且附上了搭建教程和软件&#xff0c;安卓和苹果双端都能用&#xff0c;实用方便&#xff01; 优化内容&…

力扣647-回文子串(Java详细题解)

题目链接&#xff1a;力扣647-回文子串 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一个d…

软考高级:中台相关知识 AI 解读

中台&#xff08;Middle Platform&#xff09;是近年来在软件开发和企业架构中兴起的一种理念和架构模式&#xff0c;尤其在中国的互联网企业中得到了广泛应用。中台的核心思想是通过构建一个共享的服务和能力平台&#xff0c;支持前端业务的快速迭代和创新&#xff0c;从而提升…

【学习笔记】TLS/SSL握手之Records

TLS / SSL会话是由记录&#xff08;Records&#xff09;所组成&#xff0c;有4种records HandshakeAlertChange Cipher SpecApplication DataHandshake和Alert Records被分为子类型&#xff08;Subtypes&#xff09;&#xff1a; Handshake&#xff1a;Client HelloHandshake&a…

塑料瓶回收标志分级检测系统源码分享

塑料瓶回收标志分级检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Co…

QT编译之后的debug包下运行程序双击运行出现无法定位程序输入点__gxx_personlity_seh0于动态链接库

1.出现这个错误的原因是&#xff1a; 缺少如下文件&#xff1a; 2.解决方法&#xff1a; 在运行程序.exe所在的目录执行&#xff1a;windeployqt untitled.exe&#xff08;指打包的运行程序&#xff09; 3.如果执行提示由于找不到qt5core.dll,无法继续执行代码和无法识别win…

第十一章 从0-1搭建一个简单的JavaWeb系统(三)

目录 一、工程代码结构 二、代码实现 三、运行效果 四、未完待续 本章节的每一段代码&#xff0c;建议全部自己敲一遍&#xff0c;加深印象&#xff0c;切勿直接复制黏贴。 一、工程代码结构 本章节实现注销&#xff08;退出&#xff09;功能&#xff0c;以下图片中标红的…

无线感知会议系列【4】【基于WiFi和4G/5G的非接触无线感知:挑战、理论和应用-2】

前言&#xff1a; 本篇重点分享一下该论文 《Human Respiration Detection with Commodity Wifi Devices: Do User Location and Body Orientation Matter》 接 2020年北京智源大会 张大庆老师的一个报告 参考&#xff1a; https://blog.csdn.net/chengxf2/article/detai…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十集:制作后坐力系统Recoil和小骑士的生命系统和受伤系统

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作后坐力系统Recoil 1.使用代码实现扩展新的后坐力行为2.为敌人脚本添加后坐力行为3.为小骑士添加后坐力行为二、制作小骑士的生命系统和受伤系统 1.制作…

sqlserver 合并重复行数据,取有值的字段

我有这样的一个需求&#xff0c;先看数据 上面的记录&#xff0c;圈起来的 数据关键字段是重复的&#xff0c;但有的字段不一样&#xff0c; 我现在想合并为一条&#xff0c;特殊字段&#xff0c;取有值的 搜了很多行转列&#xff0c;都不是我需要的 不过有了启发&#xff0…

【自动驾驶】基于车辆几何模型的横向控制算法 | Pure Pursuit 纯跟踪算法详解与编程实现

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

从零开始学习Python

目录 从零开始学习Python 引言 环境搭建 安装Python解释器 选择IDE 基础语法 注释 变量和数据类型 变量命名规则 数据类型 运算符 算术运算符 比较运算符 逻辑运算符 输入和输出 控制流 条件语句 循环语句 for循环 while循环 循环控制语句 函数和模块 定…

一文学会 Java 8 的Predicates

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 在这份详细的指南中&#xff0c;您将了解 Java Predicates&#xff0c;这是 Java 8 中一个新颖且有用的特性。本文解释了 Java Predicates 是什么以及如何在各种情况下使用它们。 在这份详尽的指南中…

JVM 几种经典的垃圾收集器

目录 前言 Serial Serial Old ParNew Parallel Scavenge Parallel Old CMS收集器 garbage first 收集器 前言 回顾一下之前的几种垃圾收集算法: JVM java主流的追踪式垃圾收集器-CSDN博客文章浏览阅读646次&#xff0c;点赞22次&#xff0c;收藏16次。简要介绍了几…

AI大模型教程 Prompt提示词工程 AI原生应用开发零基础入门到实战【2024超细超全,建议收藏】

在AGI&#xff08;通用人工智能&#xff09;时代&#xff0c;那些既精通AI技术、又具备编程能力和业务洞察力的复合型人才将成为最宝贵的资源。为此&#xff0c;我们提出了‘AI全栈工程师’这一概念&#xff0c;旨在更精准地描述这一复合型人才群体&#xff0c;而非过分夸大其词…

RocketMQ消费者消费的时候,宕机了,消息会丢失吗?

一个消息从生产者产生&#xff0c;到被消费者消费&#xff0c;主要经过这3个过程&#xff1a; 因此,本文将从以下这几个维度来回答: 生产者如何保证不丢消息 存储端如何保证不丢消息 消费者如何保证不丢消息 最后消费者消费的时候,宕机,消息会不会丢呢? 1. 生产者如何保证…

SaaS 软件转型计划

目录 一、转型目标 1、背景与趋势分析 2、转型策略与实施路径 3、预期成果与展望 二、现状分析 1、产品评估&#xff1a;从传统到SaaS的华丽转身 2、客户群体洞察&#xff1a;倾听需求&#xff0c;引领变革 3、销售渠道优化&#xff1a;拓宽路径&#xff0c;触达更多客…

如何高效绘制ER图?

在数据驱动的时代&#xff0c;实体-关系图&#xff08;ER图&#xff09;作为数据建模的核心工具&#xff0c;对于理解、设计和优化数据库结构至关重要。然而&#xff0c;传统的手绘或复杂软件绘制ER图方式往往效率低下且难以协作。幸运的是&#xff0c;ProcessOn在线绘图工具以…