news 2026/3/5 2:30:00

关于javaSE异常的处理(看这一篇就够了)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
关于javaSE异常的处理(看这一篇就够了)

目录

一、异常是什么

1.异常的概念

2.异常的分类

二、异常的处理

1.防御式编程

2.(异常的抛出)throw的使用

3.异常的声明-throws

4.捕获异常-try-catch捕获并处理异常

5.finally关键字起到

三、异常的处理流程

四、总结


一、异常是什么

1.异常的概念

异常是指在程序执行过程中发生的意外或错误情况,这些情况会中断正常的程序流程。异常通常由程序无法控制的内部或外部因素引发,例如无效输入,资源不足或逻辑错误。

2.异常的分类

2.1异常分为:

(1)编译时异常(除了RuntimeException):在代码编译阶段被检测到的错误,通常由语法错误或类型不匹配引起。这类异常必须修复后才能成功编译。

public class Person { private String name; private String gender; int age; // 想要让该类⽀持深拷⻉,覆写Object类的clone⽅法即可 @Override public Person clone() { return (Person)super.clone();//这里会报错,你要声明这里会报CloneNotSupportedException这个异常 } } 编译时报错: Error:(17, 35) java: 未报告的异常错误java.lang.CloneNotSupportedException; 必须对其进⾏捕获或声明以便抛出

(2)运行时异常(RuntimeException):在程序运行过程中发生的错误,例如空指针引用、数组越界或算术溢出。这类异常可能不会立即导致程序崩溃,但会破坏正常逻辑。(运行后窗口报错Exception)

(3)逻辑异常:由程序逻辑错误引发的异常,例如无限循环或错误的业务规则。这类异常需要通过代码审查和测试来发现。

2.2 异常就是一个类

Error类:这是java虚拟机无法解决的严重问题,比如:jvm的内部错误、资源耗尽,典型代表:StackOverflowError和OutOfMemoryError,一旦发生回力乏术。

Exception类:异常产生后程序员可以通过代码进行处理,使程序继续执⾏。⽐如:感冒、发烧。我 们平时所说的异常就是Exception。

二、异常的处理

1.防御式编程

错误在代码中是客观纯在的。因此我们要让程序出现问题的时候及时通知程序员。

1.1LBYL:Look Before You Leap.在操作之前就做充分的检查.即:事前防御型

boolean ret = false; ret = 登陆游戏(); if (!ret) { 处理登陆游戏错误; return; } ret = 开始匹配(); if (!ret) { 处理匹配错误; return; } ret = 游戏确认(); if (!ret) { 处理游戏确认错误; return; } ret = 选择英雄(); if (!ret) { 处理选择英雄错误; return; } ret = 载⼊游戏画⾯(); if (!ret) { 处理载⼊游戏错误; return; } ......

(缺陷:正常流程和错误处理流程代码混在⼀起,代码整体显的⽐较混乱)

2.EAFP:It's Easier to Ask Forgiveness than Permission.先正常运行,遇到问题再解决(事后认错)

try { 登陆游戏(); 开始匹配(); 游戏确认(); 选择英雄(); 载⼊游戏画⾯(); ... } catch (登陆游戏异常) { 处理登陆游戏异常; } catch (开始匹配异常) { 处理开始匹配异常; } catch (游戏确认异常) { 处理游戏确认异常 } catch (选择英雄异常) { 处理选择英雄异常; } catch (载⼊游戏画⾯异常) { 处理载⼊游戏画⾯异常; } ......

(优势:正常流程和错误流程是分离开的,程序员更关注正常流程,代码更清晰,容易理解代码 异常处理的核⼼思想就是EAFP)

针对eafp型解决方案我们有五方面的学习使用(throw、try、catch、finally、throws)

2.(异常的抛出)throw的使用

在java中我们通过throw来抛出一个指定的异常对象,将错误信息告知给调用者具体语法如下:

throw new XXXException("异常产生的原因")

注意事项:

1.throw必须在方法体内部

2.抛出的对象必须是Exception 或者 Exception的子类对象

3.如果抛出的是RunTimeException或者RunTimeException的子类,则可以直接交给jvm来处理

4.如果抛出的是编译时异常,用户必须处理,否则无法通过编译

5.异常一旦抛出,其后的代码就不会执行

3.异常的声明-throws

throws 关键字⽤于在⽅法声明中列出该⽅法可能抛出的异常,它告诉调⽤者这个⽅法可能会抛出某 些异常,调⽤者需要处理这些异常。使⽤throws 实际上是将异常的处理责任转移给了调⽤该⽅法 的代码

public static void funcction(int a) throws CloneNotSupportedException{ if(a == 10){ throw new CloneNotSupportedException(); } }

注意:

1.throws必须跟在方法的参数列表之后

2.声明的异常必须是Exception 或者Exception的子类

3.方法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可。

public class Config { File file; // FileNotFoundException 继承⾃ IOException public void OpenConfig(String filename) throws IOException{ if(filename.endsWith(".ini")){ throw new IOException("⽂件不是.ini⽂件"); } if(filename.equals("config.ini")){ throw new FileNotFoundException("配置⽂件名字不对"); }

4.调用声明抛出异常的方法时,如果该异常是编译时异常时,调用者必须处理,或者继续使用throws抛出

public static void main(String[] args) throws IOException { Config config = new Config(); config.openConfig("config.ini"); }

将光标放在抛出异常方法上,alt+Insert快速处理:

4.捕获异常-try-catch捕获并处理异常

throws对异常并没有真正处理,⽽是将异常报告给抛出异常⽅法的调⽤者,由调⽤者处理。如果真正 要对异常进⾏处理,就需要try-catch。

语法格式:

try{ //将可能出现异常的代码 }catch(要捕获的异常类型 e){ //对异常的正常处理,处理完成跳出try-catch }finally{ //一定会执行的代码 }//finally可添加可不添加看自己需求

实例:

public class Config { File file; public void openConfig(String filename) throws FileNotFoundException{ if(!filename.equals("config.ini")){ throw new FileNotFoundException("配置⽂件名字不对"); } // 打开⽂件 } public void readConfig(){ } public static void main(String[] args) { Config config = new Config(); try { config.openConfig("config.txt"); System.out.println("⽂件打开成功"); } catch (IOException e) { // 异常的处理⽅式 //System.out.println(e.getMessage()); // 只打印异常信息 //System.out.println(e); // 打印异常类型:异常信息 e.printStackTrace(); // 打印信息最全⾯ } // ⼀旦异常被捕获处理了,此处的代码会执⾏ System.out.println("异常如果被处理了,这⾥的代码也可以执⾏"); } }

(IOException是编译时异常的父类哦)

注意事项:

1.try代码块内抛出异常位置后的代码将不会执行

2.如果抛出异常类型与catch里的异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往抛,直到jvm收到后中断程序

3.try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获

public static void main(String[] args) { int[] array = {1, 2, 3}; try { System.out.println("before"); // array = null; System.out.println(array [100]); System.out.println("after"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("这是个数组下标越界异常"); e.printStackTrace(); } catch (NullPointerException e) { System.out.println("这是个空指针异常"); e.printStackTrace(); } System.out.println("after try catch"); }

如果多个异常的处理⽅式是完全相同,也可以写成这样:

catch (ArrayIndexOutOfBoundsException | NullPointerException e) { ... }

如果异常之间具有⽗⼦关系,⼀定是⼦类异常在前catch,⽗类异常在后(否则子类异常不会运行)

4. 可以通过⼀个catch捕获所有的异常,即多个异常,⼀次捕获

public static void main(String[] args) { int[] arr = {1, 2, 3}; try { System.out.println("before"); arr = null; System.out.println(arr[100]); System.out.println("after"); } catch (Exception e) { e.printStackTrace(); } System.out.println("after try catch"); }

不推荐,因为这样写不知道自己怎么解决对应的异常(乱喝药的感觉)

5.finally关键字起到

5.1在写程序时,有些特定的代码,不论程序是否发⽣异常,都需要执⾏,⽐如程序中打开的资源:⽹络 连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进⾏回收。另外,因为异常会引发程序的跳转,可能导致有些语句执⾏不到,finally就是⽤来解决这个问题的

问题:既然finally和try-catch-finally后的代码都会执⾏,那为什么还要有finally呢?

看下面的代码:

public class TestFinally { public static int getData(){ Scanner sc = null; try{ sc = new Scanner(System.in); int data = sc.nextInt(); return data; }catch (InputMismatchException e){ e.printStackTrace(); }finally { System.out.println("finally中代码"); } System.out.println("try-catch-finally之后代码"); if(null != sc){ sc.close(); } return 0; } public static void main(String[] args) { int data = getData(); System.out.println(data); } } // 正常输⼊时程序运⾏结果: 100 finally中代码 100

(上述程序,如果正常输⼊,成功接收输⼊后程序就返回了,try-catch-finally之后的代码根本就没有执 ⾏,即输⼊流就没有被释放,造成资源泄漏。存在即合理)

注意:finally中的代码一定会执行,一般用来做资源清理的扫尾工作。在finally中尽量不要用return(编译器警告)

三、异常的处理流程

关于"调⽤栈":⽅法之间是存在相互调⽤关系的,这种调⽤关系我们可以⽤"调⽤栈"来描述.在JVM中有⼀块内存空 间称为"虚拟机栈"专⻔存储⽅法之间的调⽤关系.当代码中出现异常的时候,我们就可以使⽤ e.printStackTrace(); 的⽅式查看出现异常代码的调⽤栈.

看下面的例子(如果本⽅法中没有合适的处理异常的⽅式,就会沿着调⽤栈向上传递):

public static void main(String[] args) { try { func(); } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } System.out.println("after try catch"); } public static void func() { int[] array = {1, 2, 3}; System.out.println(array[100]); }

、运行结果(at后的错误就是通过e.printStackTrace()这个显示的):

如果向上⼀直传递都没有合适的⽅法处理异常,最终就会交给JVM处理,程序就会异常终⽌(和我们最开 始未使⽤try-catch时是⼀样的).

public static void main(String[] args) { func(); System.out.println("after try catch"); } public static void func() { int[] arr = {1, 2, 3}; System.out.println(arr[100]); }

运行结果:

(明显after try catch没有打印)也就是说异常没有处理一直向上传递最后到jvm。

异常处理流程总结:

1.程序先执行try中的代码

2.如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配。

3.如果找到匹配的异常类型,就会执行catch代码

4.如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者。

5.无论是否找到匹配的异常类型,finally中的代码都会被执行到(在该方法结束之前执行)。

6.如果上层调用者也没有处理了异常,就会继续向上传递。

7.一直到main方法也没有合适的代码处理异常,就会交给jvm来进行处理,此时程序就会终止。

四、总结

看到这里,想必你对java中异常有了一定的了解,还有问题评论区留言。最后可以写一个用户登录功能(用异常)让自己更加熟练

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/24 7:38:50

54、深入解析STREAMS机制:从流头操作到终端控制

深入解析STREAMS机制:从流头操作到终端控制 1. 流头操作:qattach()与qdetach() 当打开一个模块或驱动程序时, qattach() 函数会被调用。其主要作用是为驱动程序或模块设置一个队列对,并调用其 open 函数。 qattach() 的参数之一是一个现有的队列对,新的队列对将链…

作者头像 李华
网站建设 2026/3/4 14:55:57

12、C++ 数据序列化与文件处理实战

C++ 数据序列化与文件处理实战 在 C++ 编程中,数据序列化和文件处理是非常重要的部分。本文将详细介绍如何使用不同的库进行 XML、JSON 数据的序列化和反序列化,以及如何创建包含图像的 PDF 文件和处理 ZIP 归档文件。 1. XML 数据的序列化和反序列化 在 C++ 标准库中,没…

作者头像 李华
网站建设 2026/2/27 3:50:02

三相四桥臂逆变器接不平衡与非线性负载时的调制与控制算法的MATLAB/Simulink仿真模型...

三相四桥臂逆变器MATLAB/Simulink仿真模型,接不平衡负载时的调制算法。 接非线性负载时的多PR控制器并联算法。 提供仿真模型、设计报告及参考文献三相四桥臂逆变器这玩意儿在新能源和微电网里属于硬核装备。接上吹风机、电机这类不平衡负载时,常规的三桥…

作者头像 李华
网站建设 2026/2/28 13:33:41

14、SQLite数据库中电影数据的管理与操作

SQLite数据库中电影数据的管理与操作 1. SQLite简介 SQLite是一个用C语言编写的进程内关系型数据库管理库,它并非客户端 - 服务器数据库引擎,而是嵌入到应用程序中的。整个数据库,包括表、索引、触发器和视图,都包含在一个单一的磁盘文件中。由于访问数据库意味着访问本地…

作者头像 李华
网站建设 2026/2/28 20:07:46

Windows系统文件Windows.Services.TargetedContent.dll缺少损坏问题 下载修复

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/3/2 6:56:21

设备预测性维护技术拆解与落地实战

在工业智能化落地进程中,设备预测性维护技术已成为开发者构建智能运维体系的核心抓手。但实际开发中,多数团队面临“协议适配难、算法落地繁、系统对接贵”的痛点——某自动化团队为适配10种品牌设备,花费3个月开发协议解析模块;某…

作者头像 李华