异常
Error和Exception
Java异常体系
Throwable是整个Java异常体系的*父类,其带有两个子类Error和Exception,Exception有两个子类RuntimeException和非RuntimeException
从概念角度解析java的异常处理机制
Error:
表示系统致命的错误,程序是无法处理这些错误的,编译器不做检查
一般是指与JVM相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法栈调用溢出。
*Error,OutOfMemoryError
对于这类错误,java编译器不去检查它们,并且对于这类错误导致的应用程序中断,
仅靠程序本身是无法恢复和预防的,遇到这样的错误建议让程序终止。
Exception:
程序可以处理的异常,可以被捕获并且可能会被恢复
遇到这样的错误尽可能去处理,使程序恢复运行而不是随意去终止它
两者体现了java设计者对不同异常情况的分类
本质的区别:Error使程序无法处理的错误,Exception是程序可以处理的异常
RuntimeException:运行时的异常,不可预知的,程序应当自行避免
比如,数组下标越界,访问空指针等是不可预知的,但是在编写程序时,我们可以通过检查变量
是否为null来避免空指针异常
非RuntimeException:可预知的,从编译器角度讲是必须处理的异常,如果不处理,程序编译不通过
比如IOException,SQLException等
(由于文件不存在而打开文件失败引起的异常)
从责任角度上讲
1)Error属于JVM需要负担的责任
2)RuntimeException是程序应该负担的责任
3)其他的Exception及可检查Exception都是java编译器应该承担的责任
如图:只有Checked Exception 编译器报错,在编译器看来它是必须要追踪和处理的异常,
异常处理思路
一般用try...catch语句处理,在catch中编写相应的处理逻辑,至于什么样的处理逻辑则依据具体的业务逻辑而定,
一般思路是理解这种Exception的成因,再根据成因和实际业务去处理,比如FileNotFoundException是由于某个文件句柄没有找到造成的。
再在catch中加入某个路径下不存在该文件,方便理解
不要抽象化异常类型即不要抛出异常的父类来泛化异常,因为本身异常就是为了定位问题,不要违背异常的初衷。
对于Error和RuntimeException,上层程序没有处理相关异常的义务,但是对于Checked Exception就必须处理下层帅锅上来的异常,不接不行,
如果上层知道怎么处理异常,则用try...catch将其处理,否则通过throws继续层层向上抛,直到被处理或则到顶层抛出异常为止。
如果main是最顶层,继续throws则会直接终止程序打印相关的异常,一旦异常被抛出,后面的方法就不执行
常见的Error和Exception
RuntimeException
1)NullPointerException - 空指针引用异常
2)ClassCastException - 类型强制转换异常
3)IllegalArgumentException - 传递非法参数异常
4)IndexOutOfBoundsException - 下标越界异常
5)NumberFormatException - 数字格式异常
非RuntimeException
1)ClassNotFoundException - 找不到指定class的异常
2)IOException - IO操作异常
Error
1)NoClassDefFoundError - 找不到class定义的异常
成因:
a)类依赖的class或jar包不存在
b)类文件存在,但是存在不同的域中
c)大小写问题,javac编译的时候是无视大小写的,很可能编译出来的class文件就与想要的不一样
2)*Error - 深递归导致栈被耗尽而抛出的异常
3)OutOfMemoryError - 内存溢出异常