Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解
发布时间 - 2026-01-11 00:09:26 点击率:次1、java标准异常概述

Throwable表示任何可以作为异常被抛出的类,有两个子类Error和Exception。从这两个类的源代码中可以看出,这两个类并没有添加新的方法,Throwable提供了所以方法的实现。Error表示编译时和系统错误。Exception是可以被抛出的异常类。RuntimeException继承自Exception(如NullPointerException),表示运行时异常,JVM会自动抛出.
2、自定义异常类
自定义异常类方法: 通过继承Throwable或Exception。异常类的所有实现都是基类Throwable实现的,所以构造自定义异常类完全可以参考Exception和Error类。我们只要添加上自定义异常类的构造方法就可以了
<span style="font-size:16px;">package demo.others;
/**
* 自定义异常类方法
* 1、通过继承Throwable
* 2、通过继承Exception
*
* @author Touch
*/
public class MyExceptionDemo extends Exception {
private static final long serialVersionUID = 1L;
public MyExceptionDemo() {
super();
}
public MyExceptionDemo(String message) {
super(message);
}
public MyExceptionDemo(String message, Throwable cause) {
super(message, cause);
}
public MyExceptionDemo(Throwable cause) {
super(cause);
}
}
</span>
3、异常栈及异常处理方式
可以通过try、catch来捕获异常。捕获到的异常。下面的示例演示了几种常用异常处理方式
<span style="font-size:16px;">package demo.others;
import mine.util.exception.MyException;
public class ExceptionDemo1 {
public void f() throws MyException {
throw new MyException("自定义异常");
}
public void g() throws MyException {
f();
}
public void h() throws MyException {
try {
g();
} catch (MyException e) {
//1、通过获取栈轨迹中的元素数组来显示异常抛出的轨迹
for (StackTraceElement ste : e.getStackTrace())
System.out.println(ste.getMethodName());
//2、直接将异常栈信息输出至标准错误流或标准输出流
e.printStackTrace();//输出到标准错误流
e.printStackTrace(System.err);
e.printStackTrace(System.out);
//3、将异常信息输出到文件中
//e.printStackTrace(new PrintStream("file/exception.txt"));
//4、重新抛出异常,如果直接抛出那么栈路径是完整的,如果用fillInStackTrace()
//那么将会从这个方法(当前是h()方法)作为异常发生的原点。
//throw e;
throw (MyException)e.fillInStackTrace();
}
}
public static void main(String[] args) {
try {
new ExceptionDemo1().h();
} catch (MyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
</span>
运行结果:
f g h main mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.f(ExceptionDemo1.Java:7) at demo.others.ExceptionDemo1.g(ExceptionDemo1.Java:11) at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35) mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7) at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11) at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35) mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7) at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11) at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35) mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:30) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
分析上面的程序,首先main函数被调用,然后是调用h函数,再g函数、f函数,f函数抛出异常,并在h函数捕获,这时将依次从栈顶到栈底输出异常栈路径。
4、异常链
有时候我们会捕获一个异常后在抛出另一个异常,如下代码所示:
<span style="font-size:16px;">package demo.others;
import java.io.IOException;
import mine.util.exception.MyException;
public class ExceptionDemo2 {
public void f() throws MyException {
throw new MyException("自定义异常");
}
public void g() throws Exception {
try {
f();
} catch (MyException e) {
e.printStackTrace();
throw new Exception("重新抛出的异常1");
}
}
public void h() throws IOException {
try {
g();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IOException("重新抛出异常2");
}
}
public static void main(String[] args) {
try {
new ExceptionDemo2().h();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
</span>
运行结果:
mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32) java.lang.Exception: 重新抛出的异常1 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32) java.io.IOException: 重新抛出异常2 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
从结果中我们可以看出,异常栈变小了。也就是说丢失了最原始的异常信息。怎样保存最原始的异常信息呢?Throwable类中有个Throwable cause属性,表示原始异常。通过接收cause参数的构造器可以把原始异常传递给新异常,或者通过initCause()方法。如下示例:
<span style="font-size:16px;">package demo.others;
import java.io.IOException;
import mine.util.exception.MyException;
public class ExceptionDemo2 {
public void f() throws MyException {
throw new MyException("自定义异常");
}
public void g() throws Exception {
try {
f();
} catch (MyException e) {
e.printStackTrace();
throw new Exception("重新抛出的异常1",e);
}
}
public void h() throws IOException {
try {
g();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
IOException io=new IOException("重新抛出异常2");
io.initCause(e);
throw io;
}
}
public static void main(String[] args) {
try {
new ExceptionDemo2().h();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
</span>
结果:
mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34) java.lang.Exception: 重新抛出的异常1 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34) Caused by: mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) ... 2 more java.io.IOException: 重新抛出异常2 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34) Caused by: java.lang.Exception: 重新抛出的异常1 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) ... 1 more Caused by: mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) ... 2 more
从结果中看出当获取到“重新抛出异常2的时候,同时可以输出原始异常“重新抛出的异常1“和原始异常”自定义异常,这就是异常链。
5、finally的使用
finally子句总是执行的,通常用来做一些清理工作,如关闭文件,关闭连接等
下面举几个finally的例子:
<span style="font-size:16px;">// 读取指定路径文本文件
public static String read(String filePath) {
StringBuilder str = new StringBuilder();
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(filePath));
String s;
try {
while ((s = in.readLine()) != null)
str.append(s + '\n');
} finally {
in.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str.toString();
}</span>
分析:如果调用in = new BufferedReader(new FileReader(filePath));时发生异常,这时是一个文件路径不存在的异常,也就是说并没有打开文件,这时将会直接跳到catch块,而不会执行try...finally块(并不是finally子句)里面的语句in.close();此时不需要关闭文件。
再看一个例子,会导致异常的丢失
<span style="font-size:16px;">package demo.others;
import mine.util.exception.MyException;
public class ExceptionDemo3 {
public void f() throws MyException {
throw new MyException("异常1");
}
public void g() throws MyException {
throw new MyException("异常2");
}
public static void main(String[] args) {
try {
ExceptionDemo3 ex = new ExceptionDemo3();
try {
ex.f();
} finally {
ex.g();//此时捕获g方法抛出的异常,f方法抛出的异常丢失了
}
} catch (MyException e) {
System.out.println(e);
}
}
}
</span>
结果:mine.util.exception.MyException: 异常2
此时异常1就丢失了
或者这样写:
<span style="font-size:16px;">package demo.others;
import mine.util.exception.MyException;
public class ExceptionDemo3 {
public void g() throws MyException {
throw new MyException("异常2");
}
public static void main(String[] args) {
ExceptionDemo3 ex = new ExceptionDemo3();
try {
ex.g();
} finally {
//直接return会丢失所以抛出的异常
return;
}
}
}
</span>
6、异常的限制
(1)当覆盖方法时,只能抛出在基类方法的异常说明里列出的那些异常,有些基类的方法声明抛出异常其实并没有抛出异常,这是因为可能在其子类的覆盖方法中会抛出异常
(2)构造器可以抛出任何异常而不必理会基类构造器所抛出的异常,派生类构造器异常说明必须包含基类构造器异常说明,因为构造派生类对象时会调用基类构造器。此外,派生类构造器不能捕获基类构造器抛出的异常。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# Java
# 常用类解析
# java异常机制
# 异常栈
# 异常处理方式
# 异常链
# 异常丢失详解
# 抛出
# 自定义
# 子句
# 将会
# 子类
# 这两个
# 可以看出
# 派生类
# 丢失了
# 最原始
# 都是
# 是一个
# 也就是说
# 几个
# 有个
# 不需要
# 这就是
# 并在
# 能在
# 可以通过
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】
微信小程序 闭包写法详细介绍
php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】
Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门
如何在Windows 2008云服务器安全搭建网站?
香港服务器租用费用高吗?如何避免常见误区?
公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?
Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制
实现点击下箭头变上箭头来回切换的两种方法【推荐】
制作电商网页,电商供应链怎么做?
如何快速完成中国万网建站详细流程?
千库网官网入口推荐 千库网设计创意平台入口
Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
Linux系统命令中tree命令详解
桂林网站制作公司有哪些,桂林马拉松怎么报名?
Laravel如何与Docker(Sail)协同开发?(环境搭建教程)
Android实现代码画虚线边框背景效果
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
Laravel如何使用Livewire构建动态组件?(入门代码)
如何构建满足综合性能需求的优质建站方案?
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
网页设计与网站制作内容,怎样注册网站?
Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】
网站制作大概多少钱一个,做一个平台网站大概多少钱?
Laravel如何配置Horizon来管理队列?(安装和使用)
南京网站制作费用,南京远驱官方网站?
高性能网站服务器部署指南:稳定运行与安全配置优化方案
Laravel如何使用Service Container和依赖注入?(代码示例)
高端云建站费用究竟需要多少预算?
深圳网站制作培训,深圳哪些招聘网站比较好?
免费视频制作网站,更新又快又好的免费电影网站?
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
Laravel怎么使用Intervention Image库处理图片上传和缩放
Laravel Admin后台管理框架推荐_Laravel快速开发后台工具
在centOS 7安装mysql 5.7的详细教程
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
Laravel如何创建自定义Facades?(详细步骤)
香港服务器部署网站为何提示未备案?
Laravel如何构建RESTful API_Laravel标准化API接口开发指南
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
如何基于云服务器快速搭建个人网站?
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
怎么用AI帮你为初创公司进行市场定位分析?
Laravel如何使用Blade模板引擎?(完整语法和示例)
Laravel如何生成API文档?(Swagger/OpenAPI教程)
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能
中山网站推广排名,中山信息港登录入口?

