java异常处理01
java异常处理高级技巧
什么是Java异常?
当Java程序的正常行为被意外行为中断时,会发生故障。这种故障被称为异常。例如,程序尝试打开文件以读取其内容,但该文件不存在将产生异常。Java将异常分为几种类型,所以让我们考虑每一种类型。
检查异常
Java将(例如FileNotFoundException, IOException)引起的异常分类为已检查的异常。Java编译器会检查这些异常,并且在异常发生的位置要求进行捕获处理或者向上抛出(throws)。需要注意的是检查异常属于编译器的行为,要求你必须在代码中捕获或向上抛出(throws)。
运行时(非检查)异常
例如程序进行强制转换(cast),这种可能存在转换失败的异常就是另一种异常。即运行时异常(RuntimeException)。和检查不同,编译器不会检查你在代码中是否进行处理或抛出。运行时异常通常来自编写的不良代码,因此应由程序员修复。
错误(Error)
指一些非常严重,通常无法进行修正必须要重启程序的异常。例如, 尝试从JVM分配内存,但没有足够的可用内存来满足请求(OutOfMemoryError)。运行时尝试调用加载类文件但类文件但无法找到时(NoClassDefFoundError)。对于错误您永远不应该尝试捕获并自己处理错误,因为JVM可能已经无法从中恢复正常。
Throwable及其子类
Java提供了表示不同类型异常的类层次结构。java.lang
包的Throwable
类是所有异常类的超类。
/ └────Throwable ├────Error │ ├────NoClassDefFoundError │ └────OutOfMemoryError └────Exception ├────RuntimeException │ ├────IllegalArgumentException │ └────NullPointerException ├────FileNotFoundException └────IOException (注: 该图使用https://github.com/harbby/gadtry Graph功能绘制)
注意:通常您不应该以任何方式捕获和处理Throwable。
Exception类
Throwable有两个直接的子类。其中一个子类是Exception。Java提供了许多直接子类的异常类Exception
。比如:
-
SQLException 表示发生了jdbc异常,来自
java.sql
包中 -
IOException 表示发生了I/O异常,来自
java.io
包中
注意,每个Exception
子类名称都以Exception
单词结尾。该约定使得易于识别该类异常。
您可能想自定义使用自己的Exception检查异常
。下面自定义示例:
public class MyException extends Exception { public MyException(String message) { super(message); } public MyException(String message, Throwable cause) { super(message, cause); } public MyException(Throwable cause) { super(cause); } }
Error类
Throwable另一个直接的子类是Error
,描述了一个合理的应用程序不应该尝试处理的严重问题 - 例如内存不足溢出,栈溢出,或者尝试加载无法找到的类。例如:
- OutOfMemoryError 内存溢出
- StackOverflowError 栈溢出
- NoClassDefFoundError 尝试加载无法找到的类时触发
注意:通常您不应该以任何方式捕获和处理Error类异常。
RuntimeException类
RuntimeException异常或其子类实例化是未经检查的异常。直接父类是Exception。RuntimeException和其分类Exception 声明相同的构造函数(具有相同的参数列表)。它通常表示一个可能由不良代码引起的运行时异常。下面是它的一些示例:
- NullPointerException 空指针异常,java最常见异常。过多的该异常通常意味您需要提高代码编写技巧。
- IllegalArgumentException 验证异常,通常表示参数非法或不正确的状态。
- ClassCastException 类型转换异常
NullPointerException异常优化:
- 尝试使用
java.util.Optional<T>
作为方法返回值,使用Optional.empty()取代return null
; - 使用将字符串放在前面
"str".equals(arg)
- 做好方法或构造函数的入参检查。
this.args = Objects.requireNonNull(inArgs, "inArgs is null");
- 返回空集合而不是null。
return new String[0]
orreturn Collections.emptyMap()
- 方法入参和返回使用
long,int
而非包装类Intger,Long
异常抛出
C语言通常return全局错误变量来通常调用者。而java则使用抛出异常对象来通知调用者。了解如何以及何时抛出异常是Java编程一个非常重要技能。通常您只抛出Exception
或RuntimeException
的子类实例化的对象。抛出异常有两个步骤。
- 使用
throw new 异常
语句抛出异常对象。 - 在方法上使用
throws 异常
语句告知编译器(对于检查异常这是必须的)。
throw抛出异常:
throw new SQLException(); throw new FileNotFoundException("not find file " + fileName);
异常抛出是指将异常对象从当前方法抛出到JVM。然后JVM会在异常表中查找合适异常处理逻辑(catch)。如何没有找到则JVM会退出当前方法的调用栈,从上级调用者(方法)的异常表中继续寻找。如果找到它将使用该处理代码进行处理异常。如果JVM最后在main()方法的异常表中依然没有找到合适处理逻辑(catch)那么JVM将会发出消息-1然后退出。
注意: 异常处理通常非常昂贵,您不该在任何时候使用异常处理逻辑来处理您的正常业务
throws告知编译器:
从方法中抛出检查异常时,需要在方法上添加抛出标志来通知编译器。
public static void main(String[] args) throws SQLException {}
总结
该篇文档总结java异常的分类和各自的特点。下面是一些关键点总结:
-
强制你处理或抛出
检查异常
属于编译器的行为,对于它编译器要求你必须在代码中捕获或向上抛出(throws)。 -
永远不要试图catch Error错误尝试捕获并自己处理错误,因为JVM可能已经无法从中恢复正常。
-
永远不要以任何方式直接catch捕获和处理Throwable, 因为Error是它子类。
-
异常处理通常代价非常昂贵,不要试图用来处理您的正常业务。
-
过多的NullPointerException异常意味着你需要提高代码编写技巧。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【本人秃顶程序员】使用Spring Cloud Stream和RabbitMQ实现事件驱动的微服务
←←←←←←←←←←←← 快!点关注 让我们展示如何使用Spring Cloud Stream来设计事件驱动的微服务。首先,Spring Cloud Stream首先有什么好处?因为Spring AMPQ提供了访问AMPQ工件所需的一切。如果您不熟悉Spring AMPQ,请查看此repo,其中包含许多有用的示例。那么为什么要使用Spring Cloud Stream ......? Spring Cloud Stream概念 Spring Cloud Stream通过Binder概念将使用过的消息代理与Spring Integration消息通道绑定在一起。支持RabbitMQ和Kafka。 Spring Cloud Stream将基础架构配置从代码中分离为属性文件。这意味着即使您更改了底层代理,您的Spring Integration代码也将是相同的! 示例中的Spring Cloud Stream概念(RabbitMQ) 让我们有一个名为streamInput的交换,它有两个队列streamInput.cities和streamInput.persons。现在让我们将这两个队列插...
- 下一篇
缓存伪共享问题以及解决方案缓存行填充
缓存伪共享 共享对象存在同一个缓存中,由于MESI协议,一个对象中一些不需要改变的属性因为其他改变的属性,导致整个对象的缓存进入到M被修改状态。 MESI缓存一致性协议:https://blog.csdn.net/huangyueranbbc/article/details/84554271 目前的CPU是通常按照32或者64字节的缓存行(Cache Line)进行读取,如果读取的数据在同一个CacheLine,就存在缓存伪共享的问题。 对象被放入一个CacheLine中,根据MSEI协议,其中一个属性改变,其他所有没有改变的属性也变得不可共享。 填充Cache Line缓存块 通过填充对象,将对象中常被改变的属性和不常改变的属性分开到不通缓存Cache Line中。避免缓存的伪共享。 未填充对象: public class DataPadding{ int value; long modifyTime; boolean flag; long createTime; char key; } 对象结构: # Running 64-bit HotSpot VM. # Usin...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器