难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJ IDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.try-catch
try和catch是一对好兄弟,它们在一起的时间最长,感情最好,这主要是因为我们在实际开发中经常使用它们。前面我们在 一文中介绍过它们,这里呢就不再赘述了,不清楚的小伙伴们可以去看看咯。
这里给一张它们两人的合照吧:
2.异常匹配
今天我们首要任务就是教大家认识异常匹配。
什么叫“异常匹配”?
当异常被抛出时,异常处理系统会按照catch的书写顺序找出参数与异常类型相匹配的第一个处理程序(catch),然后进入catch子句执行,此时异常得到了处理,之后不再继续查找。
定义有点长这里给大家分词解释+举例说明。
第一句:“ 当异常被抛出时 ”
从句子中可以看出需要抛出一个异常。
第二句:“ 异常处理系统会按照catch的书写顺序找出参数与异常类型相匹配的第一个处理程序(catch) ”
此句子里面提到“ 找出参数与异常类型相匹配的第一个处理程序 ”,像此例中catch参数类型是IOException,try里面抛出的异常类型也是IOException,一看就相匹配。
这样就成功地完成了一次匹配。
那么不匹配的情况是什么样的呢?
就是抛出的异常类型和catch参数类型不一致。例如IOException和ClassNotFoundException就不匹配:
上面演示了一些单个catch的情况,如果多个catch的情况呢?从“ 异常处理系统会按照catch的书写顺序找出参数与异常类型相匹配的第一个处理程序(catch) ”这句话我们也能感受到有多个catch进行异常匹配的情况。下面举例说明。
上述程序抛出了两个异常IOException和ClassNotFoundException,我们对其分别进行catch操作。当发生异常时,异常处理系统就会按照catch的书写顺序(从上至下)开始查找相匹配的catch进行执行。
例如,当发生IOException时,执行第一个catch:
当发生ClassNotFoundException时,执行第二个catch:
第二句解释完了,接着来看后面三句:“ 然后进入catch子句执行,此时异常得到了处理,之后不再继续查找。 ”
后面三句是说当我们异常被catch到以后,此异常就算是被处理了,当异常被处理完之后,异常处理系统就结束查找过程。
这个也很好理解,比如,我们程序发生IOException,匹配到第一个catch:
此时后面还有一个catch,它的参数类型是ClassNotFoundException,这个catch就不再继续匹配了,无论后面还有多少个catch都不再进行匹配了。
至此,异常匹配解释完了,下面看看怎么使用一个catch捕获所有异常。
3.使用一个catch捕获所有异常
怎么才能使用一个catch捕获所有异常呢?
使用所有异常的父类即可。
所有异常的父类是?
是Exception。
下面通过一个例子来演示一下如何使用catch捕获所有异常。
演示:
请使用一个catch捕获所有异常。
请观察程序代码。
代码:
Main类:
结果:
从运行结果来看,程序写得没有问题,我们的确通过一个catch捕获了所有异常。
重点:
为什么一个catch可以捕获所有异常?
因为异常匹配时,不需要异常类型和catch参数类型完全一致,是catch参数类型的子类也可以匹配到。
简而言之就是,因为IOException和ClassNotFoundException正是Exception的子类,所以一个参数类型为Exception的catch子句就够了。
4.使用一个catch捕获多个异常
接下来是教大家如何使用一个catch捕获多个异常。
多个异常?
嗯,就是同时在一个catch里面捕获两个及以上的异常。
那就演示一下吧。
演示:
请使用一个catch捕获多个异常。
请观察程序代码。
代码:
Main类:
结果:
从运行结果来看,程序没有问题。
来看看程序代码是怎么写的,首先我们在try代码块里面抛出两个异常IOException和ClassNotFoundException:
因为if条件表达式的缘故,它们两个异常中间必然会抛出一个异常。而抛出它们两个中的任意一个,都会被我们catch捕获到。
为什么抛出它们两个异常中的任意一个都会被捕获到呢?
因为单个catch块可以处理多种类型的异常。此功能可以减少代码重复并减少捕获过于宽泛的异常。
在catch子句中,指定块可以处理的异常类型,并使用 竖线 (|)分隔每个异常类型。
这个 竖线(|) 就是 或 的意思。
上述例子中, catch中的参数类型表示我既能捕获IOException,也能捕获ClassNotFoundException。当try代码块里面发生这两个异常中的任意一个,我都能捕获到。
5.多个catch分别捕获异常
这一小节是最容易的,因为之前章节中多次出现这种情况。下面我们就来看看,多个catch分别捕获异常的情况。
演示:
请使用多个catch分别捕获异常。
请观察程序代码。
代码:
Main类:
结果:
从运行结果来看,程序写得没有问题,结果也符合预期。
看一下程序代码:
这里的话,我们抛出了两个异常IOException和ClassNotFoundException,然后呢,我们又使用两个catch分别去捕获IOException和ClassNotFoundException。
实际运行的时候,执行的是抛出IOException:
故执行结果就是:
程序就这么简单,其实分别来捕获异常这种写法在日常开发中很常见,大家也会逐渐熟悉起来。
接下来,又到了重点时刻,请大家注意。
6.多个catch时,父类异常放在最后【重点】
今天的重中之重:
就两句话,第一句: 多个catch时
前置条件是多个catch,一个catch此定义不存在的,一定要是多catch。
例如:
第二句: 父类异常放在最后
像上图代码这样的不行,为什么呢?
Exception是IOException和ClassNotFoundException的父类,怎么能放在它们的前面。
为什么不能放在它们前面?
因为父类异常会将后面的子类异常覆盖掉,通俗来讲就是每次异常匹配的都是父类先进行匹配,如果是子类异常的话,父类异常仍然匹配成功,这样就没有后面子类异常什么事,所以子类异常写在父类异常没有意义。
结合例子来看,我们运行程序,看看执行结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/main/Main.java
Error:(21, 10) java: 已捕获到异常错误java.io.IOException
Error:(23, 11) java: 已捕获到异常错误java.lang.ClassNotFoundException
这里编译就直接不通过。所以希望大家千万要记住,不要将父类异常放在子类异常的前面。
总结
- 当异常被抛出时,异常处理系统会按照catch的书写顺序找出参数与异常类型相匹配的第一个处理程序(catch),然后进入catch子句执行,此时异常得到了处理,之后不再继续查找。
- 异常匹配时,不需要异常类型和catch参数类型完全一致,是catch参数类型的子类也可以匹配到。
- 单个catch块可以处理多种类型的异常。此功能可以减少代码重复并减少捕获过于宽泛的异常。
- 在catch子句中,指定块可以处理的异常类型,并使用竖线(|)分隔每个异常类型。
- 多个catch时,父类异常放在最后。
至此,Java中catch与异常匹配相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
下一章
“全栈2019”Java异常第十三章:访问异常堆栈跟踪信息
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!