【Java基础知识】 异常处理机制
“欲渡黄河冰塞川,将登太行雪满山。” 系统运行,风云不测,睹始知终,秋去冬来,一叶落而知秋。
1. 什么是异常?
所有使我们程序提前终止,或者没有向预想方向去执行的错误统称为异常。
2. 异常的分类?
所有异常都由Throwable
继承而来,即Exception
和Error
都继承自Throwable
注:Java中只有Throwable类型的实例才可以被抛出(throw)或者捕获(try..catch)
(1)Error
Error是指在正常情况下不太可能出现的错误,它与代码的编写无关。通常是表示运行时JVM出现的问题,比如系统内部错误、或者资源不足等。
常见的有: OutOfMemoryError
( 内存溢出 ) 、 VirtualMachineError
(虚拟机错误)、 NoClassDefFoundError
(类定义错误)
(2)Exception
Exception是指程序运行时,可以预料到的错误,Exception
又分为以下两类
可检查异常 (Exception)
需要我们在程序中必须进行显式的捕获处理,否则将会编译报错,比如常见的有IOException、SQLException
不可检查异常 ( RuntimeException ):
常见的有
NullPointerException
(空指针)、ArrayIndexOutOfBoundException
(下标越界异常)。是否需要去捕捉,程序本身不要求我们强制去做这些。但是可以避免代码在运行过程中的逻辑错误。
注意:
阿里Java开发手册中提到,如果可以进行预检测的RuntimeException不应该通过catch的方法进行处理。比如NullPointExceotion。可以先进行非控的判断,比如if(obj != null){…}
看了上面的内容,也就很轻松的去应对面试官问的问题 『Exception和Error有什么区别?』 当然,异常处理常作为面试过程中的夺命连环call。为了方便加深上面问题的答案,从网上找到了一张图。
3.异常处理
代码中的异常处理主要针对可检查异常。
(1)通过try…catch 语句来处理
(2)通过throws/throw将异常抛出交给上层处理
4.异常处理注意事项
1、谨慎使用异常处理
try..catch会造成程序的额外开销,所以建议只捕获关键的代码,切忌不要用try包住一个很大的代码块。
Java每实例化一个Exception,就会对当时的栈进行快照。如果操作比较频繁,那么对资源的开销就不能被忽略。
2、在finally代码块中对资源进行清理
如下代码,正常执行时没有任何问题,但是在关闭资源之前一旦出现异常,就会造成资源无法释放。
3、不要用异常做流程控制,条件控制
异常设计的初衷是为了解决程序运行中的各种意外情况,切异常处理的效率比条件判断的要低很多
4、catch时,请分清稳定代码和不稳定代码
稳定代码指的是无论如果都不会再出错的代码,对于非稳定代码进行catch时,尽可能区分异常类型,再做对应的异常处理。
灵魂三问:
- 哪里发生了异常?
- 谁来处理异常?
- 如何处理异常?
首先需要明确异常在哪里发生,在代码中是通过try-catch来发现异常的,但是有些程序员将大段代码定义在一个try-catch语句块中,这样非常不便于定位问题,是一种不负责任的做法。捕获异常时,要分稳定代码,和非稳定代码;
- 稳定代码:无论如何都不会发生异常的代码;例如 int a = 0;
- 异常捕获:针对非稳定的代码,捕获时要取分异常类型,并做相应的处理;
其次,判断谁来处理异常,先区分 throw 和throws的区别:
- throw : 方法内部抛出具体异常类对象的关键字
- throws: (1)作用在方法的声明上,表示如果抛出异常,则由该方法的调用者来进行异常处理;(2)主要的声明这个方法会抛出会抛出某种类型的异常,让它的使用者知道捕获异常的类型。(3)出现异常是一种可能性,但不一定会发生异常。
了解了throw和throws的区别后,再来判断当前捕获的异常是否需要自己处理,如果异常在当前方法的处理范围之内,且没有必要对外透出,那么就直接捕获异常并做相应的处理,否则向上抛出,由上层方法或者框架来处理。
异常分类结构
try 代码块
Try—catch—finally 是处理异常的三部曲;但是不能只有try这个光杆司令;
- try代码块:监视代码执行过程,一旦发生异常则直接跳转至catch,如果没有catch,则直接跳转至finally;
- catch代码块:可选执行的代码块,如果没有任何异常发生,则不会执行,如果发生异常则进行处理或向上抛出,这一切都在catch代码块中执行。
- finally代码块:必选执行的代码块,不管是否异常发生,即使发生 OutOfMemeryError也会执行,通常用于处理善后的清理工作;
注意:
(1)finally是在return表达式后执行的,此时简要return的结果已经被暂存起来,待finally代码块执行后将暂存的结果返回;
(2)不管程序代码块是否处于try块中,甚至包括catch块中代码,只要执行该代码时出现了异常,系统都会自动生成一个异常对象,如果程序没有为这段代码定义任何catch块,java运行环境肯定找不到处理该异常的catch块,程序肯定在此退出。
(3)try块后可以有多个catch块,try块后使用多个catch块是为了针对不同异常类提供的不同的异常处理方式。当系统发生不同意外情况时,系统会生成不同的异常对象,java运行时就会根据该异常对象所属的异常类来决定使用哪个catch块来处理该异常。
(4)通常情况下,如果try块被执行一次,则try块后只有一个catch块会被执行,绝不可能有多个catch块被执行,除非在循环中使用类continue开始下一次循环,下一次循环又重新运行了try块,这才可能导致多个catch块被执行。
(5)进行异常捕获时,一定要记住先捕获小的异常,再捕获大的异常
5.遇到的问题
- finally和try中的return哪个先执行?
- try中有return, 会先将值暂存到本地变量中,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。
- 当try与finally语句中均有return语句,会忽略try中return。
相关文章
- 详解面试中常被问到的那些异常问题
6. try-with-resource如何优雅的关闭io流
JAVA的一大特性就是JVM会对内部资源实现自动回收,即自动GC,给开发者带来了极大的便利。但是JVM对外部资源的引用却无法自动回收,例如数据库连接,网络连接以及输入输出IO流等,这些连接就需要我们手动去关闭,不然会导致外部资源泄露,连接池溢出以及文件被异常占用等。
传统的手动释放外部资源一般放在一般放在try{}catch(){}finally{}机制的finally代码块中,因为finally代码块中语句是肯定会被执行的,即保证了外部资源最后一定会被释放。同时考虑到finally代码块中也有可能出现异常,finally代码块中也有一个try{}catch(){},这种写法是经典的传统释放外部资源方法,显然是非常繁琐的。
6.1 传统写法操作io流
例如如下读取的文件的io流,我们之前可能会这样写
public class Main {public static void main(String[] args) {FileInputStream fileInputStream =null;try {fileInputStream = new FileInputStream(new File("/Users/laoniu/a.txt")); //打开流byte[] bytes = new byte[1024];int line = 0; //读取数据while ((line = fileInputStream.read(bytes))!= -1){System.out.println(new String(bytes,0,line));}} catch (IOException e) {e.printStackTrace();}finally {if (fileInputStream != null){ //不为空try {fileInputStream.close(); //关闭流} catch (IOException e) {e.printStackTrace();}}}}
}
6.2 使用try-with-resource写法优雅操作io流
try-with-resources 是 JDK 7 中一个新的异常处理机制,它能够很容易地关闭在 try-catch 语句块中使用的资源。所谓的资源(resource)是指在程序完成后,必须关闭的对象。try-with-resources 语句确保了每个资源在语句结束时关闭。所以实现了 java.lang.AutoCloseable 接口(其中,它包括实现了 java.io.Closeable 的所有对象),可以使用作为资源。
public class Main {public static void main(String[] args) {//把打开流的操作都放入try()块里try( FileInputStream fileInputStream = new FileInputStream(new File("/Users/laoniu/a.txt"))) {byte[] bytes = new byte[1024];int line = 0;while ((line = fileInputStream.read(bytes))!= -1){System.out.println(new String(bytes,0,line));}} catch (IOException e) {e.printStackTrace();}}
}
在try()中可以编写多个文件io流或网络io流。让我们看看java编译器是怎么帮我们实现的
借助idea查看编译后的代码
可以看到编译后的代码,java编译器自动替我们加上了关闭流的操作。所以跟我们自己关闭流是一样的。try-with-resource这样优雅的写法还是不错的,让代码看起来不那么臃肿。
注意jdk1.7以后才可以用,更多请关注官网:https://docs.oracle.com/javase/8/docs/technotes/guides/language/try-with-resources.html
- JDK 7 引入的 try-with-resources 语句的原理和用法,以及介绍了 JDK 9 对 try-with-resources 的改进,使得用户可以更加方便、简洁的使用 try-with-resources 语句。
- 作为 Milling Project Coin 的一部分, try-with-resources 声明在 JDK 9 已得到改进。如果你已经有一个资源是 final 或等效于 final 变量,您可以在 try-with-resources 语句中使用该变量,而无需在 try-with-resources 语句中声明一个新变量。
相关文章
- try - with - resource
【Java基础知识】 异常处理机制相关推荐
- Java基础知识——异常处理
目录 异常概述 异常体系结构 异常的分类 常见异常举例 异常处理方式 方式一:try-catch-finally finally的使用 方式二:throws 手动抛出异常 自定义异常 异常 ...
- JAVA基础知识+基础代码
Java基础知识 异常处理 try {} catch(Exception e) {} void work() throws Exception {} //抛出异常 throw new Exceptio ...
- 【转】Java基础知识整理
本博文内容参考相关博客以及<Java编程思想>整理而成,如有侵权,请联系博主. 转载请注明出处:http://www.cnblogs.com/BYRans/ PDF版下载链接:<Ja ...
- 《Java和Android开发实战详解》——1.2节Java基础知识
本节书摘来自异步社区<Java和Android开发实战详解>一书中的第1章,第1.2节Java基础知识,作者 陈会安,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...
- java 基础知识总结
Java基础知识总结 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思 ...
- 【转】java基础知识总结
Java基础知识总结 本博文内容参考相关博客以及<Java编程思想>整理而成,如有侵权,请联系博主. 转载请注明出处:http://www.cnblogs.com/BYRans/ PDF版 ...
- java(5)---Java基础知识大全
Java基础知识大全 一.基础知识: 1.JVM.JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. java语言是跨平 ...
- Java基础知识(七) 输入输出流
Java基础知识 输入输出流 1. Java IO流的实现机制是什么 2. 管理文件和目录的类是什么 3. Java Socket是什么 4. Java NIO是什么 5. 什么是Java序列化 6. ...
- java基础知识-----转
基础知识: 1.C++或Java中的异常处理机制的简单原理和应用. 当J***A程序违反了J***A的语义规则时,J***A虚拟机就会将发生的错误表示为一个异 常.违反语义规则包括2种情况.一种是J* ...
- java基础知识之加强
Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...
最新文章
- 【PL/SQL】Excel批量往数据库中插入数据:
- 您在2016年会做什么? Apache Spark,Kafka,Drill等
- 第一季1:HI3518EV200的体验
- VBA各种查询方法介绍和应用举例
- 属性定义为 not null unique_Spring Data with MySQL (实体定义)
- javascript设计模式-适配器模式
- 服务器装哪个操作系统好,服务器装哪个操作系统好
- 【Yarn】工作机制及任务提交流程
- Linux Tricks —— 快速清空文本文件内容、文本内容追加(tee)
- 为确保网络中不同计算机,在计算机网络中,为确保网络中不同计算机之间能正确地传送和接收数据,它们必须遵循一组共同的规则和约定。这些规则、约定或标准通常被称为____。...
- oracle迁移数据到mysql
- MacOS系统离线安装包11.x-12.x
- 计算机音乐新年好呀,新年好呀新年好 伴奏
- 简述数字电路在计算机的应用,数字电路应用举例
- 最简单DIY基于ESP8266的智能彩灯⑤(用C#调色板UI通过串口控制WS2812彩灯)
- 新手小白如何做自媒体自媒体入门视频教程(3G教程)
- SoundPool循环播放
- 12 款适用于开发人员的最佳 Web 开发软件
- 关于Python3爬虫抓取豆瓣电影的案例-利用正则表达式
- LATTICE FPGA 工具介绍之ACTIVE-HDL 建立工程及仿真步步来(2)
热门文章
- 基于golang的Json选择器
- 元宇宙产业委与南京信息工程大学举办“元宇宙与智能技术创新论坛”
- 关于使用preparestatement来实现模糊查询
- group by 与 where, having以及顺序
- Matlab数组,复数数组实部、虚部、模、幅角
- SkeyeVSS以智能手段助力乘梯消防安全电梯AI智能监控解决方案
- 刘源谷俊山黑龙江八一农垦大学教务网络管理系统
- 《鬼谷子本经阴符七术》原文全文
- 小米android q适配机型,小米官方公布安卓Q适配机型以及内测时间:最早2019年Q4季度开始...
- 增量编码器与Arduino连接(读取编码器脉冲数)