Java学习|Exception和Error有什么区别?

典型回答:
     Exception和Error都继承了Throwable类,java中只有Throwable类型的实例才能被Throw(抛出)或者catch(捕获)。
     Exception是程序正常运行中可能预料到的异常情况,应该被捕获,进行相应的处理。
     Error是非正常情况,是不应该出现的,不需要抛出或者捕获处理。比如OOM,是JVM的一种异常状态,是Error的子类。
     Exception分为可检查异常和不检查异常。
          可检查异常,必须在代码中显示的捕获处理。
          不检查异常,也就是所谓的运行时异常,比如NPE(空指针),AIOOME(数组下标越界),一般是能够通过编码避免的逻辑错误。
下面放一个类关系图:
    
开发中,我认为我们要掌握的主要有以下两点:
     1.理解Throwable,Exception,Error的设计和分类。如:掌握那些应用最广的子类,以及如何自定义异常。
          比如NoClassDefFoundError和ClassNotFoundException的区别?
     2.理解java中对于Throwable的操作的元素和实践。如:try-catch-finally语句块,throw,throws等。也要懂得处理的场景。
          随着java的发展,引入了一些新的特性,如在jdk7以后,引入了try-with-resource语法,能够使我们关闭连接的语句更精炼。
          try-with-resource其实是语法糖,编译后依然是之前的语法。并且需要句柄对象(比如FileInputStream对象)实现了AutoCloseable接口
 
处理异常的基本原则:
     1.不要使用类似Exception类这样的通用异常来捕获异常。
     2.不要生吞异常。
     
处理异常:
     最差的方式是生吞异常,会掩盖程序中出现的问题。
     如果实在不知道如何处理异常,可以保留原有异常信息,直接抛出或者构建新的异常抛出。在更高的层面,因为有更清晰的业务逻辑,可能能知道该如何处理异常。
     
NoClassDefFoundError和ClassNotFoundException的区别
     NoClassDefFoundError是一个错误(Error),而ClassNOtFoundException是一个异常,在Java中对于错误和异常的处理是不同的,我们可以从异常中恢复程序但却不应该尝试从错误中恢复程序。
ClassNotFoundException的产生原因主要是:
     Java支持使用反射方式在运行时动态加载类,例如使用Class.forName方法来动态地加载类时,可以将类名作为参数传递给上述方法从而将指定类加载到JVM内存中,如果这个类在类路径中没有被找到,那么此时就会在运行时抛出ClassNotFoundException异常。
解决该问题需要确保所需的类连同它依赖的包存在于类路径中,常见问题在于类名书写错误。
     另外还有一个导致ClassNotFoundException的原因就是:当一个类已经某个类加载器加载到内存中了,此时另一个类加载器又尝试着动态地从同一个包中加载这个类。通过控制动态类加载过程,可以避免上述情况发生。
 
NoClassDefFoundError产生的原因在于:
     如果JVM或者ClassLoader实例尝试加载(可以通过正常的方法调用,也可能是使用new来创建新的对象)类的时候却找不到类的定义。要查找的类在编译的时候是存在的,运行的时候却找不到了。这个时候就会导致NoClassDefFoundError.
     造成该问题的原因可能是打包过程漏掉了部分类,或者jar包出现损坏或者篡改。解决这个问题的办法是查找那些在开发期间存在于类路径下但在运行期间却不在类路径下的类。
 
 
在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 如无必要,勿用异常。
posted @ 2018-07-30 09:43  星辰河流  阅读(150)  评论(0编辑  收藏  举报