二者之间的区别
Exception和Error都是继承了Throwable类,在Java中只有Throwable类型的实例才可以被抛出throw或者捕获catch,它是异常处理机制的基本组成
Exception是程序中正常运行中,可以预料道德意外情况,可以被捕获,进行相关的处理
Error在正常情况下,不大可能出现的情况,绝大部分的Error都会导致程序处于非正常、不可恢复状态。比如常见的OutOfMemoryError
Exception分为可检查异常和不可检查异常
可检查异常在代码里必须显示的进行捕获处理。
不可检查异常就是运行时异常,类似NullPointerException、ArrayIndexOutOfBoundsException,通常是可以通过编码避免的逻辑错误,具体根据需要判断是否需要捕获,并不会在编译期强制要求
异常捕获需要遵循的原则:try{} catch(Exception e){}
尽量不要捕获类似Exception这样的通用异常,而是应该捕获特定的异常。比如更希望让一些RuntimeException被触发,而不是捕获
不要在捕获异常后直接掩盖问题(生吞异常),如果我们不把异常抛出来,或者没有输出到日志,程序可能在后续代码以不可控的方法结束。这样不好判断究竟是哪里抛出异常。碰到这种我们不知道怎么处理的异常,我们可以选择保留原有异常的信息,直接再抛出。
自定义异常需要考虑两点:
是否需要定义成可检查异常,因为这种类型设计的初衷就是为了从异常情况中恢复
在保证诊断信息足够的同时,还要考虑避免包含敏感信息,这样可能导致潜在的安全问题。比如用户的数据一般不可以输出到日志中
Java的异常处理机制带来的性能损失
try-catch 代码段会产生额外的性能开销,会影响JVM对代码进行优化,所以建议仅仅捕获必要的代码段,尽量不要一个大的try包住整段代码;利用异常控制代码流程,也远比条件语句(if/else、switch)要低效
Java每实例化一个Exception,都会对当时的栈进行快照。如果发生的非常频繁了,这个新能德开销也是不可忽略的
NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
NoClassDefFoundError发生在初始阶段,是一个error
常见的场景:
类依赖的class或者jar不存在
类文件存在,但存在不同的域中
大小写问题,javac编译时是无视大小写的,很有可能编译出来的class文件与想要的不一样
ClassNotFoundException:找不到指定的class,发生在加载阶段,是一个异常
常见的场景:
调用class的forName方法,找不到指定的类
ClassLoader中findSystemClass,找不到指定的类
ClassLoader中loadClass,找不到指定的类
总结:
遇见异常最好就地解决,不是只捕捉,不处理
不要在finally代码块中处理返回值
按照我们的惯性认知:当遇到return语句的时候,执行函数会立刻返回。但是,在Java语言中,如果存在
finally就会有例外。除了return语句,try代码块中的break或continue语句也可能使控制权进入finally代码块。
尽量不要在try代码块中调用return、break或continue语句,否则就要确保finally不会改变函数的返回值
当一个try后跟多个catch需要先捕获小异常在捕获大异常
finally中的代码始终是执行的,目的是为了清理资源(除非线程或者程序被中断)