为什么需要异常

理想的情况下,程序是不会有BUG的。但是现实的情况是:处处都可能引发BUG,比如一个糟糕的输入、需要访问的资源不存在、网络出现抖动、服务器资源不足等等。这就要求我们的程序需要一个机制来解决以下问题:

报告当前的错误信息

中断,发生了错误的逻辑不向下执行代码

抛出一个信号,让程序对此做出判断进行进一步的处理。

Java设计了一个异常处理的错误捕获机制来解决这些问题。

异常层次结构

image.png

可以看到,所有的异常都是由Throwable继承而来,而在下一层分为了2个分支:Error和Exception

Error

Error类层次结构描述的是Java运行时系统的内部错误和资源耗尽错误。(如著名的OutOfMemoryError、StackOverflowError),一旦出现了这种错误,马上系统会通知用户,并尽力让程序安全地终止,就无能为力了。也就是说,这是程序员难以去控制的(排除个别场景压力测试引发的)。

Exception

Exception其实也分为2个分支:

RuntimeException-由于程序错误导致的异常

下面我们举几个例子:

ClassCastException-错误的类型转换

ArrayIndexOutOfBoundsException-数组越界访问

NullPointerException-空指针

NoSuchElementException-访问的元素不存在

非RuntimeException-程序没有问题,因为外界资源引起的异常。(IOException)

举几个常见的例子:

FileNotFoundException-尝试打开一个不存在的文件

ClassNotFoundException-无法根据给定的字符串找到表示的类

可见,RuntimeException通常是可以通过程序员的编程能力去解决的。而对于非RuntimeException,这是不可预期的,因为谁会指定这个一个该存在的文件是否被人为地删除了呢,因此这是根据资源环境决定的.

unchecked异常与checked异常

Java语言规范将派生与Error类或者RuntimeException类的所有异常称为非检查异常,所有其他的异常称为受查异常。这是什么意思呢?也就是Java认为,OOM和RumtimeException这种都是程序运行起来才会出现的,这些应该由程序员本身去规避。而由于环境的不确定因素引发的异常,比如说IO异常,那么就需要主动去解决,你可以选择throw,或者try catch,但是你不能不处理,否则无法通过编译。

如何处理异常

check异常可以通过throws声明

throws是带有传递性的,也就是说如果方法调用链路是:A->B->C,此时C对异常声明了,那么A和B都要处理这个异常。可以选择继续向上抛出,或者try catch。如果最终都不处理,那么由对应的异常处理器进行处理。

public class ThrowsException {

/**

* 我们声明了一个不存在的文件,试图获取它的输出流,这时IDE会提示我们需要处理受检查的异常

* @param args

* @throws FileNotFoundException

*/

public static void main(String[] args) throws FileNotFoundException {

File noExitsFile = new File("D:\\logs\\notExistFile");

FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile);

}

}

使用try catch关键字处理异常

public static void main(String[] args){

File noExitsFile = new File("D:\\logs\\notExistFile");

try {

FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile);

} catch (FileNotFoundException e) {

// 实际工作中,应使用自定义异常将此错误抛出

e.printStackTrace();

}

}

如果程序中有使用到资源,应声明finally对资源进行释放,注意,不要在finally里面做return这种逻辑。

public static void main(String[] args) {

File noExitsFile = new File("D:\\logs\\notExistFile");

FileOutputStream fileOutputStream = null;

try {

fileOutputStream = new FileOutputStream(noExitsFile);

} catch (FileNotFoundException e) {

// 实际工作中,应使用自定义异常将此错误抛出

e.printStackTrace();

} finally {

if (Objects.nonNull(fileOutputStream)) {

try {

fileOutputStream.close();

} catch (IOException e) {

Logger.getGlobal().info("An exception occurred when closing the stream");

}

}

}

}

使用try-with-resource来控制你的资源

这样写是否觉得非常啰嗦,Java提供了另一种方式来释放资源更加优雅->try-with-resource,但是要确保资源类是否实现了AutoCloseable接口

try(Resource resource = new Resource()){

// do Something

}catch(IOException e){

// handle Exception

}

案例:

public static void main(String[] args) {

File noExitsFile = new File("D:\\logs\\notExistFile");

try (FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile)) {

FileDescriptor fd = fileOutputStream.getFD();

} catch (IOException e) {

// 实际工作中,应使用自定义异常将此错误抛出

e.printStackTrace();

}

}

多个资源如何声明:

public static void main(String[] args) {

File noExitsFile = new File("D:\\logs\\notExistFile");

try (FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile);

FileInputStream fileInputStream = new FileInputStream(noExitsFile);) {

FileDescriptor fd = fileOutputStream.getFD();

FileDescriptor fd1 = fileInputStream.getFD();

} catch (IOException e) {

// 实际工作中,应使用自定义异常将此错误抛出

e.printStackTrace();

}

}

处理异常的一些原则

不要使用try catch嵌套这种方式进行编程,应将可能发生异常的代码块用一个try catch包住,然后对不同的异常进行catch

尽量抛出职责足够小的异常类,不要直接抛出IOException或者RuntimeException这种通用性较强的类,这样容易定位问题

try catch住的异常必须处理,不要吞掉异常

使用throws可以让代码更加简洁,并且交由特定的异常处理类进行处理

使用Spring的声明式事务注解时,应注意只对RuntimeException进行处理,最好手动声明rollback

涉及资源使用的类需要声明finally对资源进行回收,或者使用Java7的try-with-resource

java hexits,[Java]浅谈Java的异常体系相关推荐

  1. 猿来小课Java视频教程讲师浅谈JAVA体系结构

    猿来小课Java视频教程讲师:Java体系结构中不仅定义了Java的开发编译环境,也定义了Java的运行环境.为运行Java应用程序和applet,计算机上应安装JVM和Java运行时解释器,这两个部 ...

  2. java的throw_浅谈Java的throw与throws

    浅谈Java异常 以前虽然知道一些异常的处理,也用过一些,但是对throw和throws区别还是有不太清楚.今天用实例测试一下 异常处理机制 异常处理是对可能出现的异常进行处理,以防止程序遇到异常时被 ...

  3. scale和java比较_浅谈java中BigDecimal的equals与compareTo的区别

    这两天在处理支付金额校验的时候出现了点问题,有个金额比较我用了BigDecimal的equals方法来比较两个金额是否相等,结果导致金额比较出现错误(比如3.0与3.00的比较等). [注:以下所讲都 ...

  4. java 线程aba,浅谈Java中ABA问题及避免,浅谈javaaba避免

    浅谈Java中ABA问题及避免,浅谈javaaba避免 本文主要研究的是关于Java中ABA问题及避免的相关内容,具体如下. 在<Java并发实战>一书的第15章中有一个用原子变量实现的并 ...

  5. 【Java虚拟机】浅谈Java虚拟机

    跨平台 Java的一大特性是跨平台,而Java是如何做到跨平台的呢? 主要依赖Java虚拟机,具体来说,是Java虚拟机在各平台上的实现. Java虚拟机在不同的平台有不同的实现.同一份字节码,通过运 ...

  6. java 虚拟机_浅谈Java虚拟机内存区

    1. Java 虚拟机内存区概述 我们在编写程序时,经常会遇到OOM(out of Memory)以及内存泄漏等问题.为了避免出现这些问题,我们首先必须对JVM的内存划分有个具体的认识.JVM将内存主 ...

  7. c java多态_浅谈Java多态

    什么是Java中的多态?又是一个纸老虎的概念,老套路,把它具体化,细分化,先想三个问题(注意,这里不是简单的化整为零,而是要建立在学习一个新概念时的思考框架): 1.这个东西有什么用?用来干什么的?它 ...

  8. java中hashcode_浅谈Java中的Hash值

    1.Hash值有什么用? HashMap.HashTable.HashSet,所以涉及到使用Hash值进行优化存储的地方,都会用到HashCode.HashCode是Key,这种计算为提高计算的性能. ...

  9. java 连nosql_浅谈 Java 中 MongoDB NoSQL数据库使用指南

    MongoDB是当今非常流行的一款NoSQL数据库,本文介绍如何使用MongoDB的Java驱动来操作MongoDB. 一.引入MongoDB Java Driver包 如果需要操作MongoDB的J ...

  10. java堆栈有序无序,浅谈Java并发编程系列(四)—— 原子性、可见性与有序性

    Java内存模型是围绕着在并发过程中如何处理原子性.可见性和有序性这3个特征来建立的,我们来看下哪些操作实现了这3个特性. 原子性(atomicity): 由Java内存模型来直接保证原子性变量操作包 ...

最新文章

  1. DataBinding
  2. python太难学了-为何编程那么难?新手该怎么学Python?
  3. 手机端系统提交数据的创建时间验证的问题
  4. 一张图看懂Bean的实例化过程
  5. IdentityServer4-客户端的授权模式原理分析(三)
  6. 【转】盖茨给职场新人的10句话
  7. Vue项目构建后通过Nginx/SpringBoot/Express/Egg发布
  8. LigoWave(力格微)无线网桥稳定性探秘——私有协议
  9. 158.用 Read4 读取 N 个字符read characters from file multiple calls
  10. Lintcode---二叉树的最大深度
  11. Matlab画图相关知识
  12. Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)
  13. 万物互联-stm32单片机简介、烧录、编程及其项目环境搭建
  14. 计算机word简历制作教程,用word制作个人简历的方法
  15. [工具] f.lux – 随时间改变屏幕色温护眼
  16. CNKI 中国知网全文数据库账户密码免费入口
  17. Matlab获取线粒体序列及核苷酸初步分析
  18. 用python将视频转化为图片
  19. 转使用chrome命令行:disable-web-security 实现浏览器跨域
  20. 攻壳机动队中的塔奇克马有灵魂吗?烧脑深度思考,慎点

热门文章

  1. python爬虫教程蝴蝶汤_Python 爬虫十六式 - 第五式:BeautifulSoup-美味的汤
  2. 简述php语言的特点是_PHP语言有哪些优势和特点(一)
  3. python控制多台手机,用python同时启动多个appium,并让多个手机同时执行脚本
  4. android 标题栏 fragment,切换Fragment 并更换标题栏
  5. oracle blob update,Oracle数据库中对BLOB数据的操作问题
  6. java 摸拟qq消息提示_java 仿qq消息提示框
  7. 纯前端开发案例:用 SpreadJS 搭建信息系统软件开发平台
  8. https跳转到http session丢失问题
  9. mips语言实现 f(n) = f(n-1) + 2*f(n-2) + 3*f(n-3)
  10. Linux下命令详解(-)