java面试知识点总结:异常Exception和Error
文章目录
Exception和Error的区别
相同点:
1、都是继承Throwable,在java中只有实现Throwable的才可以抛出throw和捕抓catch
不同点:
Error可能会导致jvm程序不可恢复的状态,比如OutOf的MemoryError,StackOverflowError
Exception又分为可检查checked异常和不检查异常unchecked
Throwable、Exception、Error 设计和分类
异常使用不当案例
1、违反了两大原则:忽略异常处理、捕抓大异常,吃掉小异常。
后果:有可能导致程序出错,不打印相关错误日志堆栈信息,无法有效的定位问题。
try {
// 业务代码
// …
Thread.sleep(1000L);
} catch (Exception e) {
// Ignore it
}
2、使用printStackTrace()
官方的文档,开头就是“Prints this throwable and its backtrace to the ”。问题就在这里,在稍微复杂一点的生产系统中,标准出错(STERR)不是个合适的输出选项,因为你很难判断出到底输出到哪里去了,最好使用日志工具类进行输出,并且可以管理日志。
try {
// 业务代码
// …
} catch (IOException e) {
e.printStackTrace();
}
请使用一下sl4j或者log4j
try {
// 业务代码
// …
} catch (IOException e) {
logger.error("error detail",e);
}
3、对try_catch 、finally使用不当
public int getNum(){
try {
int a = 1/0;
return 1;
} catch (Exception e) {
return 2;
}finally{
//int b = 1/0;
return 3;
}
返回3
性能相关
性能角度来审视一下 Java 的异常处理机制
-
try-catch 代码段会产生额外的性能开销,或者换个角度说,它往往会影响 JVM 对代码进行优化,所以建议仅捕获有必要的代码段,尽量不要一个大的 try 包住整段的代码;与此同时,利用异常控制代码流程,也不是一个好主意,远比我们通常意义上的条件语句(if/else、switch)要低效。
-
Java 每实例化一个 Exception,都会对当时的栈进行快照,这是一个相对比较重的操作。如果发生的非常频繁,这个开销可就不能被忽略了。
异常的问题
业界有一些声音,说异常设计是java的设计错误。
1、我们checkException进行处理,实际上基本上上出错不可能再回复程序。
2、checkedException 不兼容函数式编程funtional编程,如果你写过Lambada,相信会有体会。
可参考:
http://literatejava.com/exceptions/checked-exceptions-javas-biggest-mistake/
以上观点并不影响java的功能强大,使用广泛。
其他使用建议
在Java世界里,异常的出现让我们编写的程序运行起来更加的健壮,同时为程序在调试、运行期间发生的一些意外情况,提供了补救机会;即使遇到一些严重错误而无法弥补,异常也会非常忠实的记录所发生的这一切。
1 不要推诿或延迟处理异常,就地解决最好,并且需要实实在在的进行处理,而不是只捕捉,不动作。
2 一个函数尽管抛出了多个异常,但是只有一个异常可被传播到调用端。最后被抛出的异常时唯一被调用端接收的异常,其他异常都会被吞没掩盖。如果调用端要知道造成失败的最初原因,程序之中就绝不能掩盖任何异常。 建议先处理小异常,再处理大异常
3 不要在finally代码块中处理返回值。
4 按照我们程序员的惯性认知:当遇到return语句的时候,执行函数会立刻返回。但是,在Java语言中,如果存在finally就会有例外。除了return语句,try代码块中的break或continue语句也可能使控制权进入finally代码块。
5 请勿在try代码块中调用return、break或continue语句。万一无法避免,一定要确保finally的存在不会改变函数的返回值。
6 函数返回值有两种类型:值类型与对象引用。对于对象引用,要特别小心,如果在finally代码块中对函数返回的对象成员属性进行了修改,即使不在finally块中显式调用return语句,这个修改也会作用于返回值上。
7 勿将异常用于控制程序流程
8 如无必要,勿用异常。
9、上传下载、使用socket连接不能抛出异常,一定要finally进行关闭流操作。