【修真院XX小课堂】java异常处理机制

背景介绍

Java 为什么引入异常处理机制?

在没有异常处理机制的语言里在函数调用过程中就只能通过检查函数返回值对照错误码方式来判断函数调用是否正确执行,这会扰乱正常代码流程。使用异常处理的好处有两点。第一,异常处理让异常无法像错误码一样被忽略,必须写代码去捕获。第二,使用异常代替返回错误码,错误处理代码就能从主路径的代码中分离出来得到简化。


知识剖析

异常是什么?

程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。

Java针对异常提供的解决办法  就是异常处理机制。异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,还能保持代码的清晰。

Java虚拟机用方法调用栈来跟踪每个线程中一系列的方法调用过程。每个线程都有一个独立的方法调用栈。从Java应用程序的主线程开始入口方法main()。当一个新方法被调用时,Java虚拟机把该方法的栈结构置入栈顶,执行该方法。

当被调用的方法正常执行完毕,Java虚拟机会从调用栈中弹出该方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,则Java虚拟机寻找能捕获该异常的catch代码块。它首先查看当前方法是否存在这样的catch代码块,如果存在,那么就执行该catch代码块;否则,Java虚拟机会从调用栈中弹出该方法的栈结构,继续到前一个方法中查找合适的catch代码块。直到找到了处理该异常的代码块,当Java虚拟机追溯到调用栈的底部的方法时,也就是main方法   仍然没有找到处理该异常的代码块 打印来自方法调用栈的异常信息。这个过程就是异常追踪栈。然后终止线程。

异常的分类

根据java对异常处理的要求,可以将异常分为非检查异常和检查异常。这里的检查是对于java编译器来说的。

非检查异常指error  运行时异常 以及他们的子类这种异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常时,即使没有捕获它,也没有抛出它,还是会编译通过。

Error类也是程序不能处理的错误,比如内存不足,一般发生这种异常,JVM会选择终止程序。因此我们编写程序时应该关注Exception为父类的分支下的各种异常类。

运行异常类对应于编译错误,它是指Java程序在运行时产生的由解释器引发的各种异常。比如说空指针异常,下标越界异常。异常运行异常可能出现在任何地方,且出现频率很高,因此为了避免巨大的系统资源开销,编译器不对异常进行检查。所以Java语言中的运行异常不一定被捕获。出现运行错误往往表示代码有错误。

检查异常指除了Error 和 RuntimeException的其它异常。就是IO异常   编译器强制要求程序员为这样的异常做预备处理工作(使用try...catch...finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,否则编译不会通过。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下,而我们无法干预用户如何使用他编写的程序,所以我们应该准备好处理可能出现的异常


常见问题

在编写代码处理异常时 2种不同的处理方式:使用try...catch...finally语句块处理它。或者,在函数签名中使用throws 声明交给函数调用者去解决。

Throwthrows

Throws是方法可能抛出异常的声明,告知上一级函数这里可能抛出什么异常,是一个通知,用在方法签名

Throw是一个抛出函数的实际行为,用在代码块里面

try...catch...finally语句块里有return执行顺序:

如果finally中没有return。若在try中没有异常,则先跳去执行finally中的代码,再回来执行tryreturn。如果有异常就执行catch return之前的代码,然后执行finally,最后执行return

如果finally中有return,则以finally中的return为准,其他的return都将失效,return之前的代码都有效。


扩展思考

异常处理的原则

1、当你在写try-catch语句的时候,脑子里是知道自己要去针对哪种异常进行处理的,不要只是以防万一,加了个catch(Exception e),这是毫无意义的。而且,一个try块中可能有多个异常,对于每一类异常,要分别写一个catch进行捕获。       

 

2、针对可能出现异常的语句进行try-catch,大段代码的try-catch会非常不利于维护代码时定位异常可能发生的位置,对于肯定不会发生异常的稳定的代码,不需要放在try块中。


3try-catch虽然在功能上,可以成为流程控制的工具,达到条件分支的效果。但相比于if-else语句,java的异常处理机制使用过程中需要更多的时间与空间的开销,所以不要用异常机制去做基本的条件判断,只有在程序会因为异常而中断时进行捕获和处理。

 

4、finally块中永远不要写return语句,因为finally块中总是最后执行,他会改变预期在trycatch块中的返回值(举个例子,你在catch中捕获了一个异常并抛出e,又在finally语句中return true,这样你抛出的异常就"消失"了,因为当前函数的执行结果已经从抛出异常 转变成 return true)。另外,在使用资源对象与流对象时,要记得在finally块里关闭。


Q1:Exception e后e.toString()和e.getMessage()的区别。

A1:e.toString()获取的信息包括异常类型和异常详细消息,而e.getMessage()只是获取了异常的详细消息字符串。


Q2:接口的实现类抛出了异常,接口要不要抛出

A2:类在实现接口方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。

 

Q3:使用事务管理了还用try catch吗?

A3:不要用try catch,如果异常被catch,事务就不回滚了。


  技能树.IT修真院     
  “我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己学习的节奏,学习的路上不再迷茫”。

   这里是技能树.IT修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄1对1免费指导。

 
   快来与我一起学习吧~http://www.jnshu.com/login/1/90118367

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值