关于JAVA中的异常类及异常处理机制与基本原则

简介: 在编码过程中经常需要处理程序中的异常,然而对于异常处理也有相应的处理原则及内部处理机制,合理的异常处理机制也有利于提升程序的执行性能。

异常定义
异常是指程序在执行过程中出现了意外情况,导致程序被迫中断运行。
1、Throwable、Exception、Error 区别
Throwable类是所有异常和错误的超类,其中Exception 和 Error都继承自Throwable类。 在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。

Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。
Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
Exception 分为运行时异常和已检查异常:

    运行时异常(RuntimeException),即不检查异常,通常由应用程序逻辑错误引起,应用程序应避免此类异常。如空指针、数组越界等。
    已检查异常(Checked Exception)在代码中必须显示的进行捕获处理,这是编译期检查的一部分。假设是捕获了异常,然后恢复程序,但现实大多数情况下,都不能恢复。

Error 是程序无法处理的错误,表示运行应用程序中出现了严重的错误,一般会导致程序处于非正常的、不可恢复状态。JVM一般会选择线程终止,不便于也不需要捕获。如:虚拟机自身出现内存溢出(OutOfMemoryError)、栈溢出。

ClassNotFoundException 和 NoClassDefFoundError区别:
首先这两个类都是在类加载的过程中出现的异常。
ClassNotFoundException 类加载器在装载某个类的时候,在所有的类路径下都没有找到这个类,就会报ClassNotFoundException异常。这种情况下既使捕获了这个异常,也是无法恢复程序的,通常在执行下面的方法时容易抛出:
Class.forName()
ClassLoader.loadClass()
ClassLoader.findSystemClass()
也就是说,类加载器在加载阶段找不到类信息,此时如果直接采用反射或者类加载器的loadClass方法去动态加载一个所有classpath里面的都不存在的类,类加载器在运行时的load阶段就会直接抛出ClassNotFoundException异常。
NoClassDefFoundError 属于JVM的ERROR错误,严重级别较高。类加载器在使用阶段找不到类信息,即JVM编译时存在某个类,但是运行时却找不到,就出现了编译和运行不一致,所以就直接抛出了这个ERROR。比如类编译之后被删除了。

Java异常类层次结构图:
image.png
2、异常处理的基本原则
1)尽量不要捕获Exception这样的通用异常,而应该只捕获特定的异常。

try {
    File file = new File("");
    new FileInputStream(file);
} catch (FileNotFoundException e) {
    // ...
}

2)不要生吞异常。

 生吞异常会导致难以排查程序运行过程中出现的问题。或将异常抛出来,最好使用日志框架,详细地输出到日志系统中。

另外需要注意的地方:
尽量不要用一个大的try-catch包住整段的代码。
避免使用 e.printStackTrace() 抛出异常,对于分布式系统,如果发生异常,很难找到异常堆栈轨迹。
输出异常日志时,要考虑避免包含敏感信息,会导致潜在的信息安全问题。比如:用户数据、服务器配置等。

3、异常处理机制
异常捕获 try-catch-finally ,体现了JAVA语言的健壮性
抛出异常 throws 与 throw
两者的区别:

 throw用来在方法体内抛出异常,而throws用来在方法声明处声明异常。

两者的联系:

 如果一个方法中使用了throw关键字抛出了异常,那么要么立即用try/catch语句进行捕获,要么就是用throws进行声明,否则将出现编译错误。然而, 并不是只有使用了throw关键字之后才能使用throws关键字,语法上来说,任何一个方法都可以直接使用throws关键字,抽象方法也可以使用。

实际应用:
1)对于某些特定的业务发现异常情况时,根据自身业务情况,可以采取完善异常时的补偿机制;即当业务处理出现异常时,对当前业务多次进行重试请求。重试请求的策略根据业务的需要决定,当达到重试上限时依然无法成功,或放弃,或通过回调机制通知业务方执行失败。
2)异常信息要尽可能的全面,便于诊断业务异常过程。

异常处理带来的性能开销
1)try-catch 代码段会产生额外的性能开销,影响JVM对代码进行优化;
2)Java每实例化一个Exception,都会对当时的栈进行快照,这个操作相对比较重。如果异常非常频繁,这个开销就不能忽略了。频繁的Exception,也可能会导致服务反应变慢、吞吐量下降。

相关文章
|
2月前
|
Java 编译器 数据库连接
Java异常处理:写出更健壮的代码
Java异常处理:写出更健壮的代码
150 0
|
3月前
|
Java 程序员 数据库连接
我们详细地讲解一下 Java 异常及要如何处理
我是小假 期待与你的下一次相遇 ~
|
4月前
|
Java
java 多线程异常处理
本文介绍了Java中ThreadGroup的异常处理机制,重点讲解UncaughtExceptionHandler的使用。通过示例代码展示了当线程的run()方法抛出未捕获异常时,JVM如何依次查找并调用线程的异常处理器、线程组的uncaughtException方法或默认异常处理器。文章还提供了具体代码和输出结果,帮助理解不同处理器的优先级与执行逻辑。
121 1
|
6月前
|
SQL Java 中间件
【YashanDB知识库】yasdb jdbc驱动集成BeetISQL中间件,业务(java)报autoAssignKey failure异常
在BeetISQL 2.13.8版本中,客户使用batch insert向yashandb表插入数据并尝试获取自动生成的sequence id时,出现类型转换异常。原因是beetlsql在prepareStatement时未指定返回列,导致yashan JDBC驱动返回rowid(字符串),与Java Bean中的数字类型tid不匹配。此问题影响业务流程,使无法正确获取sequence id。解决方法包括:1) 在batchInsert时不返回自动生成的sequence id;2) 升级至BeetISQL 3,其已修正该问题。
【YashanDB知识库】yasdb jdbc驱动集成BeetISQL中间件,业务(java)报autoAssignKey failure异常
|
6月前
|
SQL druid Oracle
【YashanDB知识库】yasdb jdbc驱动集成druid连接池,业务(java)日志中有token IDENTIFIER start异常
客户Java日志中出现异常,影响Druid的merge SQL功能(将SQL字面量替换为绑定变量以统计性能),但不影响正常业务流程。原因是Druid在merge SQL时传入null作为dbType,导致无法解析递归查询中的`start`关键字。
|
6月前
|
运维 Java 程序员
Java中的异常处理方法
本文深入剖析Java异常处理机制,介绍可检查异常、运行时异常和错误的区别与处理方式。通过最佳实践方法,如使用合适的异常类型、声明精确异常、try-with-resources语句块、记录异常信息等,帮助开发者提高代码的可靠性、可读性和可维护性。良好的异常处理能保证程序稳定运行,避免资源泄漏和潜在问题。
194 5
|
7月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
464 14
|
7月前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
1248 5
|
Java 程序员 编译器
十三、Java异常处理机制详解
异常机制是指程序在执行过程中发生了不正常的情况。
十三、Java异常处理机制详解

热门文章

最新文章