Exception和Error有什么区别?
exception和error都继承了Throwable类,在java中只有Throwable类型的实例才能被捕获或者抛出,他是异常处理机制的基本组成类型。
Error是指正常情况下,不大可能出现的情况。大部分的Error会导致系统处于非正常状态、不可恢复状态。常见的有OutOfMemoryError等xxxError都是Error的子类。
Exception又分为可检查异常和不检查异常。可检查异常在源代码里必须显示的进行捕获处理。不检查异常就是所谓的运行时异常,NullPointerException等,这类不会再编译期强制要求。
Error、Exception、RuntimeException都有哪些?
Error相关
1.AWTError:当发生严重的 Abstract Window Toolkit 错误时,抛出此错误。
2.VirtualMachineError:抛出以表明Java虚拟机已损坏或已耗尽资源以使其继续运行。
1>StackOverflowError:当堆栈溢出发生时抛出
2>OutOfMemoryError:当Java虚拟机由于内存不足而无法分配对象时抛出,并且垃圾收集器不再有可用的内存
Exception相关
1.IOException:表示发生某种类型的I / O异常。 此类是由失败或中断的I / O操作产生的一般异常类。
1>EOFException:表示在输入过程中意外地到达文件结束或流结束。
2>fileNotFoundException:指示尝试打开由指定路径名表示的文件失败
2.RuntimeException:是在Java虚拟机的正常操作期间可以抛出的那些异常的超类
1>ArithmeticException:抛出异常算术条件时抛出
2>MissingResourceException:表示资源丢失
3>ClassNotFoundException:没有找到具有指定名称的类的定义
4>NullPointerException:空指针异常
5>IllegalArgumentException:抛出表示一种方法已经通过了非法或不正确的参数
6>ArrayIndexOutOfBoundsException:抛出以表示使用非法索引访问数组。 索引为负数或大于或等于数组的大小
下面举个例子看看有什么问题:
try{
....
Thread.sleep(1000L);
}catch(Exception e){
}
第一:尽量不要捕获Exception这样的通用异常,需要根据代码去捕获特定异常,就如上代码所示应该捕获InterruptedException。
第二:catch代码块中异常生吞。并没有把异常抛出,如果真的出现问题不好判断从哪里排查。
try {
// 业务代码
// …
} catch (IOException e) {
e.printStackTrace();
}
在生成过程中我们也是不允许这样去catch异常,因为什么呢?可以看看printStackTrace()的文档,“Prints this throwable and its backtrace to the standard error stream”。在复杂的生产系统中,标准出错不是个合适的输出选项,很难判断到底输出到哪里。
在分布式系统中如果发生异常,无法找到堆栈轨迹,那就是为诊断设置障碍。所以最好使用产品日志,详细的输出到日志系统。
throw early,catch later原则。
public void readPreferences(String fileName){
//...perform operations...
InputStream in = new FileInputStream(fileName);
//...read the preferences file...
}
如果fileName是null就会排除空指针异常。在实际代码中,可能是各种情况,例如获取配置失败等问题,如果第一时间抛出就能够更清晰的反应出问题。
对于下面的代码是对“throw early”的最好体现:
public void readPreferences(String filename) {
Objects. requireNonNull(filename);
//...perform other operations...
InputStream in = new FileInputStream(filename);
//...read the preferences file...
}
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
至于“catch late”,其实是我们经常苦恼的问题。捕获异常后需要怎么处理,最差的方式就是生吞。如果实在不知道怎么去处理,可以保留异常信息,在更高层面往往更清楚合适的处理方式。
从性能的角度分析JAVA异常处理机制:
- try-catch会有额外的性能开销,尽量不要把一个大的try包住一整段代码
- Exception每实例化一个都会对当时的栈进行快照。如果发生频繁,那这个开销就不能被忽略
评论留言
adrian-jser:
假如你开车上山,车坏了,你拿出工具箱修一修,修好继续上路(Exception被捕获,从异常中恢复,继续程序的运行),车坏了,你不知道怎么修,打电话告诉修车行,告诉你是什么问题,要车行过来修。(在当前的逻辑背景下,你不知道是怎么样的处理逻辑,把异常抛出去到更高的业务层来处理)。你打电话的时候,要尽量具体,不能只说我车动不了了。那修车行很难定位你的问题。(要补货特定的异常,不能捕获类似Exception的通用异常)。还有一种情况是,你开车上山,山塌了,这你还能修吗?(Error:导致你的运行环境进入不正常的状态,很难恢复)
总结:
在没有学习这篇文之前,对于捕获异常和抛出异常这两个概念很模糊。只知道捕获用try-catch,抛出用Exception;而且有的时候觉得捕获异常很麻烦,就直接将整段代码放在了try中,这种方法很不可取,以后需要改正,我相信不光是我一个人是这样吧。
下面这张图是我聚XXX的领导发的朋友圈:
希望大家能够知道异常的重要性。