基础篇:深入解析JAVA异常
目录
- 方法中发生异常,会创建一个异常对象交给JVM处理,该异常对象包含异常名称,异常描述以及异常发生时应用程序的状态。创建异常对象并交给JVM的过程称为抛出异常。这会有一系列的方法调用,这系列方法调用的有序列表叫做调用栈
- JVM会顺着调用栈去查找看是否有可以处理异常的代码,当JVM发现可以处理异常的代码时,会把发生的异常传递给它。如果JVM没有找到可以处理该异常的代码块,JVM就会将该异常转交给默认的异常处理器,默认处理器会打印出异常信息
1 异常的分类和继承关系
- Throwable是Java语言中所有错误与异常的超类。Throwable包含两个子类:Error(错误)和Exception(异常)
- Error是程序中无法处理的,这些错误是不受检异常,非代码性错误。因此,当此类错误发生时,程序不应该去处理此类错误。按照惯例,我们也不应该实现任何新的Error子类的
- Exception是程序本身可以捕获并且可以处理的异常。Exception又分为两类:运行时异常(RuntimeException)和编译时异常(受检异常)
2 几种常见异常类的解析
- RuntimeException(非受检异常)是Java在虚拟机运行期间抛出异常的超类。执行方法期间抛出的RuntimeException的任何子类都无需在throws子句中进行声明,因为它是uncheckedExcepiton。常见五种RuntimeException
- java.lang.ArithmeticException(算术异常)
- java.lang.ClassCastException(类型转换异常)
- java.lang.IllegalArgumentException(不合法的参数异常)
- java.lang.IndexOutOfBoundsException(数组下标越界异常)
- java.lang.NullPointerException(空指针异常)
- 受检异常定义: Exception 中除 RuntimeException 及其子类之外的异常。特点: Java编译器要求程序必须捕获或声明抛出这种异常
- java.io.IOException(IO流异常)
- java.lang.ClassNotFoundException(没找到指定类异常)
- java.lang.NoSuchFieldException(没找到指定字段异常)
- java.lang.NoSuchMetodException(没找到指定方法异常)
- java.lang.IllegalAccessException(非法访问异常)
- java.lang.InterruptedException(中断异常)
3 Java异常关键字
关键字 | 作用描述 |
---|---|
try{ } | 可能抛出异常的代码放在try语句块内,当try语句块内发生异常时,异常会被抛出 |
catch(e) | 捕获异常e; catch用来捕获try语句块中发生的异常,可以声明多个catch,catch里也可以捕捉多个异常 |
finally | finally语句块总会被执行。主要用于回收在try代码块里打开的资源(如数据库连接、TCP连接和文件流) |
throw | 用于抛出异常 |
throws | 声明该方法可能抛出的异常 |
- 注意: 执行try、catch或其他地方的return、throw语句前,需要执行finally内的代码。如果在finally中有return、throw语句,则在执行finally里的return或throw语句后,方法结束
public int hello(String fileName) throws RuntimeException{
int a = 10;
try{
File file = new File(fileName);
FileInputStream in = new FileInputStream(file);
return a; // 返回值10
}catch (FileNotFoundException e){
System.out.println("error occurred");
}catch (ArithmeticException | IndexOutOfBoundsException e){
System.out.println("whatever");
} finally{
System.out.println("finally");
a = 20; // finally修改a,也不会改变try里 return 10 的结局
// return a; //如果此处返回,则返回值等于 20
}
return -1;
}
4 开发过程处理异常注意点
- 抛出明确的异常且对异常进行文档说明
- 如果方法里有需要外部处理的异常,请声明throws抛出具体异常,方便调用方处理
- 在方法上声明抛出异常时,也需要进行注释说明。目的是为了给调用者提供尽可能多的信息,方便处理异常
- 使用具有标识性的消息定义异常:方便精确定位问题
- 优先捕获最具体的子类异常
- 如果先catch异常超类,如catch(Exception e),后面捕获catch(RunTimeExcption e)的代码是不会被执行的
- 不要捕获Throwable类
- 因为Throwable是Error和Exception超类,Error是JVM、系统级别错误,一般不应捕捉处理
- 捕捉异常后不要不处理:导致无法定位异常错误的发生根源,建议至少也要日志输出下
- 不要记录并抛出异常:导致同一个异常输出多条相同日志,不容易找到错误根源
- 包装新异常时不要丢弃原始的异常
- 如果丢弃原始的异常,将会丢失堆栈跟踪和原始异常的消息,会使得分析异常事件变得困难
- 注意:异常会影响性能
- 异常处理的性能成本非常高,创建一个异常非常慢,抛出一个异常又会消耗1~5ms。尽量不要使用异常来控制代码的逻辑
5 异常和AutoCloseable(1.7-JDK的语法糖)
- 在捕捉异常处理,我们经常会在try里打开资源(TCP链接,文件流)。为了防止异常发生而导致资源没被关闭,所以资源的关闭,都需要放在finally代码快里执行
- 有没有方便的方式呢?在1.7 JDK后,java提供了try–with–resource语法糖,资源对象需要实现AutoCloseable,在try()里打开资源,相关资源就会自动关闭,不再需要手动执行,不管是正常退出或异常退出
- InputStream子类都继承了AutoCloseable,自动关闭资源类FileInputStream的使用示例
File file = new File("./text.txt");
try (FileInputStream in =new FileInputStream(file)){
...//数据操作
} catch (Exception e) {
log.error(e.getMessage(), e);
...
}
6 throw和throws的区别
- throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常和非受查异常都可以被抛出
- throws 关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一个方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否则也要在方法签名中用 throws 关键字声明相应的异常
7 guava的Throwables类了解一下
- 如果需要对异常调用链操作,可以使用Throwables工具类,Throwables常用方法:
//以list的方式得到throwable的异常链
public static List<Throwable> getCausalChain(Throwable throwable)
//返回最底层的异常
public static Throwable getRootCause(Throwable throwable)
//把受检查的异常转换为运行时异常
//获取异常调用链的描述输出(每一行都有)
public static String getStackTraceAsString(Throwable throwable)
//如果异常是declaredType类似,则抛出异常,传递throwable
public static <X extends Throwable> void propagateIfInstanceOf(
@Nullable Throwable throwable, Class<X> declaredType) throws X
//当且仅当它是一个RuntimeException和Error时,或者是一个X的实例时,传递throwable
void propagateIfPossible(Throwable, Class<X extends Throwable>) throws X
//将Throwable转为RuntimeException,不建议使用此方法
public static RuntimeException propagate(Throwable throwable)
- 实例
public static void main(String args[]) throws FileNotFoundException {
try {
File file = new File("./text.txt");
FileInputStream inputStream = new FileInputStream(file);
} catch (Exception e) {
//获取异常调用栈信息,并打印(或者保存在其他地方)
String errorMsg = Throwables.getStackTraceAsString(e);
System.out.println(errorMsg);
//如果e是FileNotFoundException,直接抛出
Throwables.propagateIfInstanceOf(e, FileNotFoundException.class);
//其他Throwable 转为 RuntimeException类抛出
throw Throwables.propagate(e);
}
}
欢迎指正文中错误
关注公众号,一起交流
参考文章
基础篇:深入解析JAVA异常的更多相关文章
- 写给大忙人的ELK最新版6.2.4学习笔记-Logstash和Filebeat解析(java异常堆栈下多行日志配置支持)
接前一篇CentOS 7下最新版(6.2.4)ELK+Filebeat+Log4j日志集成环境搭建完整指南,继续对ELK. logstash官方最新文档https://www.elastic.co/g ...
- 撸基础篇系列,JAVA的NIO部分
前言:撸基础篇系列,避免每次都要从头开始看,写个自己的知识体系树 NIO 核心就是异步, 比如,复制文件,让操作系统去处理,等通知 BIO核心类 一,BIO NIO基本操作类 Bytebuffer 构 ...
- java基础篇---XML解析(二)
XML解析之最流行的方式:DOM4J dom4j是使用java语言编写的,用于读,写,操作XML的一套组件 dom4j是一个开源的java组件,可从http://sourceforge.net/pro ...
- java基础篇---XML解析(一)
XML是可扩展标记语言 在XML文件中由于更多的是描述信息的内容,所以在得到一个xml文档后应该利用程序安装其中元素的定义名称去除对应的内容,这样的操作称为XML解析. 在XML解析中W3C定义SAX ...
- 《成神之路-基础篇》JVM——Java内存模型(已完结)
Java内存模型 本文是<成神之路系列文章>的第一篇,主要是关于JVM的一些介绍. 持续更新中 Java内存模型 JVM内存结构 VS Java内存模型 VS Java对象模型(Holli ...
- 基础篇系列,JAVA的并发包 - 锁
JAVA中主要锁 synchronized Reentrantlock ReentrantReadWriteLock 问题引入 为什么需要锁? 为什么JAVA有了synchronize还需要Reent ...
- 添物不花钱学JavaEE(基础篇)- Java
Java Java是一面向对象语言 Write Once Run Anywhere Designed for easy Web/Internet applications, Mobile Widesp ...
- java基础(八)-----深入解析java四种访问权限
Java中的访问权限理解起来不难,但完全掌握却不容易,特别是4种访问权限并不是任何时候都可以使用.下面整理一下,在什么情况下,有哪些访问权限可以允许选择. 一.访问权限简介 访问权限控制: 指的是本类 ...
- 基础篇:深入解析JAVA泛型和Type类型体系
目录 1 JAVA的Type类型体系 2 泛型的概念 3 泛型类和泛型方法的示例 4 类型擦除 5 参数化类型ParameterizedType 6 泛型的继承 7 泛型变量TypeVariable ...
随机推荐
- 揭秘|一探腾讯基于Kubeflow建立的多租户训练平台背后的技术架构
腾讯业务及组织架构现状 先简单和大家介绍一下腾讯内部的业务及相关组织架构的现状,有助于帮助大家理解为什么我们会基于后面的架构来设计整套方案. 下图的应用大多数人经常会用到,比如微信.腾讯视频.游戏等等 ...
- 能卖课 会带货的CRMEB知识付费系统v1.30来了
CRMEB知识付费系统是众邦科技在疫情肆虐,国家危难时开源发布的一款产品,它的诞生是众邦人爱国情怀的一次释放,更是众邦人用技术为人们带来美好生活的一次有效实践. 知识付费系统从2020年3月发布v1. ...
- 长沙做假证u
长沙做假证[电/薇:187ヘ1184ヘ0909同号]办各类证件-办毕业证-办离婚证,办学位证书,办硕士毕业证,办理文凭学历,办资格证,办房产证不. 这是一个简单的取最大值程序,可以用于处理 i32 数 ...
- 白嫖码云Pages,两分钟的事,就能搭个百度能搜到的个人博客平台
为了攒点钱让女儿做个富二代(笑),我就没掏钱买服务器,白嫖 GitHub Pages 搭了一个博客平台.不过遗憾的是,GitHub Pages 只能被谷歌收录,无法被百度收录,这就白白损失了一大波流量 ...
- vue-element-admin改造接入后台,搭建有来商城youlai-mall后台前端管理平台
一. 前言 本篇基于有来商城youlai-mall微服务项目,搭建后台前端管理平台,技术选型希望通过本篇文章你可以,技术解决方案选择了vue-element-admin.希望通过本篇文章你可以vue- ...
- Azure Blob (三)参数设置说明
一,引言 上一篇将 Azure Blob 存储的时候,有使用到一个 .NET Core Web 项目,通过代码的方式进行操作 Azure Blob 的数据,接着上一篇的内容,今天继续看一下代码,具体 ...
- C006:多项式求值 horner法则
代码: #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { float x; do{ printf("E ...
- EMQ集群搭建实现高可用和负载均衡(百万级设备连接)
一.EMQ集群搭建实现高可用和负载均衡 架构服务器规划 服务器IP 部署业务 作用 192.168.81.13 EMQTTD EMQ集群 192.168.81.22 EMQTTD EMQ集群 192. ...
- Scrapy框架的架构原理解析
爬虫框架--Scrapy 如果你对爬虫的基础知识有了一定了解的话,那么是时候该了解一下爬虫框架了.那么为什么要使用爬虫框架? 学习框架的根本是学习一种编程思想,而不应该仅仅局限于是如何使用它.从了解到 ...
- Java枚举解读
Java枚举 枚举类概念的理解与定义 一个类的对象是有限个,确定的,我们称此为枚举类. 当需要定义和维护一组常量时,强烈建议使用枚举类. 如果一个枚举类中只有一个对象,则可以作为单例模式的实现方式. ...