难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJ IDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.异常体系
在Java异常这个大家族中,Throwable是这个异常家族中的老大,它下面有两个靠谱老弟,一个叫“Error”,一个叫“Exception”。Error老弟负责错误部门,Exception老弟负责异常部门,它们各司其职。我给它们做了一个结构图:
![6b852738eb99ee9c0fbde177fe96f7ad.png](https://img-blog.csdnimg.cn/img_convert/6b852738eb99ee9c0fbde177fe96f7ad.png)
Throwable在上一章《“全栈2019”Java异常第十六章:Throwable详解》中已经介绍过了,而Exception我们已经不陌生了,前面文章都和Exception有关,Error我们比较陌生一点,这一章章我们就着重讲解它。
2.已检查的异常
在上一章中,我们知道出于编译时检查异常的目的,Throwable和Throwable的任何子类(除Error和RuntimeException的子类)都被视为已检查的异常。
![6f8bf549c9df14f349ead2802efb322c.png](https://img-blog.csdnimg.cn/img_convert/6f8bf549c9df14f349ead2802efb322c.png)
Error不是已检查的异常,那Error是什么呢?
Error是错误。
在Java异常体系中有三种异常:
第一种异常是已检查的异常。
第二种异常是错误。
第三种异常是运行时异常。
已检查的异常在上一章已经聊过了,现在我们来聊聊错误。运行时异常放在Exception的下一章讲解。
3.错误
![57a7ade43671d43c9d23e4c77a128c6a.png](https://img-blog.csdnimg.cn/img_convert/57a7ade43671d43c9d23e4c77a128c6a.png)
Error是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题。当错误发生时,这些错误应该是无法预测或恢复的(try-catch或throws)。
当我们遇到Error时,我们不应该去使用try-catch捕获它,也不应该throws将错误抛出去。
那该如何是好?
我们应该手动排查错误出现的原因及位置,然后把它解决在程序运行之前。
这里有一点非常重要,“当我们遇到Error时,我们不应该去使用try-catch捕获它,也不应该throws将错误抛出去。”说的都是不应该,不是说不能。我们还是可以使用try-catch或throws,只是不应该这样去做。
通俗来讲就是,异常就像电脑打开某个软件,然后软件因为某个操作而崩溃了,这时你可以再重新打开一次软件,这就相当于捕获异常的操作修复好这个问题了;而错误就不一样,错误就像你电脑冒烟了,这时你肯定是修不好了,也就相当于你无法捕获这个错误去修复它。当然了,有小伙伴说电脑冒烟我能不能修复的试试?当然可以,这就和我们程序中遇到Error时,可以使用try-catch或者thorws,但是不建议你这么做。
我们来结合例子看看。
演示:
请抛出一个错误。
请观察程序代码及结果。
代码:
Main类:
![8a734e27067a3722cd16f4f1699d8a84.png](https://img-blog.csdnimg.cn/img_convert/8a734e27067a3722cd16f4f1699d8a84.png)
结果:
![2506f7ee58b6227ffa1400e9ad4cd3b9.png](https://img-blog.csdnimg.cn/img_convert/2506f7ee58b6227ffa1400e9ad4cd3b9.png)
从运行结果来看,Error不是不能被try-catch的,而且不光可以try-catch程序还被修复好了,从运行结果我们就可以看出来:
![47d29d538235a92fcadbd86aa12d383b.png](https://img-blog.csdnimg.cn/img_convert/47d29d538235a92fcadbd86aa12d383b.png)
那么我们程序本身做了什么呢?
首先,我们抛出一个Error对象,用来模拟制造一个错误:
![710fbb97bf9db350bf39ec9622bc3aee.png](https://img-blog.csdnimg.cn/img_convert/710fbb97bf9db350bf39ec9622bc3aee.png)
紧接着,我们对其进行try-catch处理:
![251a210350cb331ded996e7680756f9f.png](https://img-blog.csdnimg.cn/img_convert/251a210350cb331ded996e7680756f9f.png)
在catch中我们打印Error的堆栈跟踪信息:
![fe87f09f2244a1155350da61b9dc6204.png](https://img-blog.csdnimg.cn/img_convert/fe87f09f2244a1155350da61b9dc6204.png)
在try-catch的下面我们输出了一段话,这行代码的作用只有一个,那就是验证我们的错误是被成功修复的:
![bad260248793e8df8efb09f5d2a51326.png](https://img-blog.csdnimg.cn/img_convert/bad260248793e8df8efb09f5d2a51326.png)
程序执行结果也符合预期:
![dc0daffe4edecab6157aff97fcd5f5eb.png](https://img-blog.csdnimg.cn/img_convert/dc0daffe4edecab6157aff97fcd5f5eb.png)
可能小伙伴们说,这例子也太技术含量了吧,是不是有点太敷衍我们了?
这个例子仅仅只是演示Error可以被try-catch,下面我们来一个实际开发中的案例,而且这个错误是日常开发中偶尔会碰到的。
4.内存溢出OutOfMemoryError
OutOfMemoryError对于大多数零基础的同学来说,可能比较陌生,但是对于稍微有些开发经验的同学来说,也算是打过几次照面的。
OutOfMemoryError是什么?
OutOfMemoryError是内存溢出错误。
OutOfMemoryError什么时候会发生?
OutOfMemoryError在JVM(Java虚拟机)内存不足的情况下会发生。
大家还记得我们在讲解《“全栈2019”Java异常第十三章:访问异常堆栈跟踪信息》一章中讲到的JVM内存图吗?里面我们讲到JVM会去申请一块内存空间,这块内存空间专门是用来存放Java应用数据的(比如基本数据类型、数组、对象...等等)。当这块内存空间不足的时候,就会发生OutOfMemoryError异常。
来个例子演示一下。
演示:
请制造一个OutOfMemoryError异常。
请观察程序代码及结果。
代码:
Main类:
![da991aff95c43431421bb8ca43d4be1c.png](https://img-blog.csdnimg.cn/img_convert/da991aff95c43431421bb8ca43d4be1c.png)
结果:
![2daf3c48c84a3c2ed125ad41e1fab1e1.png](https://img-blog.csdnimg.cn/img_convert/2daf3c48c84a3c2ed125ad41e1fab1e1.png)
从运行结果来看,我们程序的确是发生了OutOfMemoryError异常。接下来,我们看看它是怎么发生的。
程序代码真的是好简单,就一行:
![be03a93198eadcffdcf3f263bc285a0c.png](https://img-blog.csdnimg.cn/img_convert/be03a93198eadcffdcf3f263bc285a0c.png)
我们创建了一个int类型的数组,只不过就是数组长度有点大,1024 * 1024 * 1024个长度。
为什么这一行代码会产生OutOfMemoryError异常,让JVM内存溢出?
因为我们在创建数组的时候,实际上就是在申请一块内存空间用,这个内存空间就是数组的地盘,而且数组在申请内存空间的时候,还会按照数据类型的大小来预支实际内存大小,我们知道一个int占4个字节,我们申请了1024 * 1024 * 1024个int这么多的4个字节,可想而知内存申请有多大,所以创建一个长度超出JVM内存大小的数组时,就会产生OutOfMemoryError异常。
有的小伙伴的JVM内存可能有足够大,所以当他运行和我一摸一摸的程序时,程序并没有崩溃,那么请这样的小伙伴再在数组长度的后面乘以1024。
为什么是1024?
因为1024在程序计算中容易换算,比如1KB=1024B(B:字节)。
像OutOfMemoryError我们就必要去捕获它了,真发生了OutOfMemoryError程序就只能是崩溃之后重新运行。
为什么没必要?
我们不知道它会什么时候出现,实际开发不像我们上面这样去写一个长度超出JVM内存大小的数组,内存的申请发生在每一行代码身上,我不知道哪一行代码运行时会造成OutOfMemoryError。
虽说没必要,但是我们有没有什么应对的措施?
有,实际开发中我们碰到OutOfMemoryError的时候就会去分析我们的程序代码,找出那个产生OutOfMemoryError的源头,修正程序。
总结
- Error是错误。它是Java异常体系中的一种。
- Error是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题。
- 当我们遇到Error时,我们不应该去使用try-catch捕获它,也不应该throws将错误抛出去。
- OutOfMemoryError是内存溢出错误。
- 实际开发中我们碰到OutOfMemoryError的时候就会去分析我们的程序代码,找出那个产生OutOfMemoryError的源头,修正程序。
至此,Java中Error相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
“全栈2019”Java异常第十六章:Throwable详解
下一章
“全栈2019”Java异常第十八章:Exception详解
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
![2881c8854b60513f9e88e08e70caa95f.png](https://img-blog.csdnimg.cn/img_convert/2881c8854b60513f9e88e08e70caa95f.png)
版权声明
原创不易,未经允许不得转载!