相信我们或多或少遇到或者听过有时候在代码里面明明try catch了异常,但是程序报错却没有捕获到错误。这个原因其实就涉及的异常体系了。我们先看看一个例子:

public class ExceptionText { public static void main(String[] args) throws Throwable{ try{ throw new Throwable(); }catch (Exception e) { System.out.println("new Throwable() is success."); } } }

下图试运行结果

java 什么时候使用try catch(面试题Java中的异常体系)(1)

我们发现我们抛出了一个Throwable异常,没有捕获到,这是为什么呢?

首先我们先弄清异常体系,Throwable是什么,Exception又是什么。

Throwable

Java中的所有异常都来⾃顶级⽗类Throwable,Throwable下有两个⼦类Exception和Error。因为Exception是他的子类所以光catch的Exception的格局不够,范围没有包括他,所以没有捕获。

error

表示系统级的错误,是java运行环境内部错误或者硬件问题,不能指望程序来处理这样的问题,除了退出运行外别无选择,它是lava虚拟机抛出的。是Throwable的子类

java 什么时候使用try catch(面试题Java中的异常体系)(2)

exception

表示程序需要捕捉、需要处理的异常,是由于程序设计的不完善而出现的问题,程序必须处理的问题。是Throwable的子类

java 什么时候使用try catch(面试题Java中的异常体系)(3)

当然Error和Exception还有很多子类,这里我们说个常见异常类运行时异常

RuntimeException

继承Exception的是检查性异常,抛出是要处理的,因为他在程序编译期间就会出现问题,继承RuntimeException见名知意是运行时发生的,所以编译期间不会出现,需要人工捕获。

java 什么时候使用try catch(面试题Java中的异常体系)(4)

当然我们也可以自定义异常,只需要继承对应的异常就可以了。

捕获不到原因

相信读到这里应该明白了为啥会捕获不到错误了,因为抛出的是Throwable这个异常超类,Exception子类肯定不包括,所以我们只需要扩大捕获范围即可。

public class ExceptionText { public static void main(String[] args) throws Throwable{ try{ throw new Throwable(); }catch (Throwable e) { System.out.println("new Throwable() is success."); } } }

运行结果成功捕获

java 什么时候使用try catch(面试题Java中的异常体系)(5)

所以我们以后在写代码时,需要精确捕获异常,考虑好程序会发生的错误,捕获相应的异常,来正确处理异常错误。

我们接下说说异常的打印信息组成和常见方法:

所处线程名字、异常类名、异常信息、异常堆栈、异常的源码,包名,类名,方法名,行数

getMessage : 错误信息的字符串解释

getCause:返回异常产生的原因,一般是原始异常如果不知道原因返回null

printStackTrace:打印异常出现的位置或原因,不建议使用,该方法会产生的字符串记录的是堆栈信息,太长太多,内存被填满,建议使用logger输出到日志文件

java 什么时候使用try catch(面试题Java中的异常体系)(6)

toString:返回String格式的Throwable信息,此信息包括Throwable的名字和本地化信息

initCause:初始化原始异常

PrintStream和PrintWriter作为产生实现重载,这样就能实现打印栈轨迹到文件或流中

常见异常:

NullPointException:空指针异常,对象是null时会出,在调用传入对象时尽量判断是否为nullldk8里面可以用Optiona对象来避免

IndexOutOfBoundsException:数组下标越界,数组的下标超过了最大值时会抛出,在选代循环时检查下标是否越界

NumberFormatException:数字类型转化异常,将非数字类型转成数字类型,将类型转化的代码catch住

ClassCastException:类型转换异常,发生在强转时,将不同类型转成同一类型,尽量少用强转,或用 instanceof(判断继承中子类的实例是否是父类的实现)做类型判断,或多用泛型

FileNotFoundException:找不到指定文件,文件路径错误或文件不存在,可能用了绝对路径检查文件是否存在,路径是否写错,多用相对路径

ClassNotFoundException:在classpath中找不到引用的类缺乏引用当前类的jar或没有设置classpath或 jar损坏,找到jar并放入classpath中或检查jar是否损坏

OutOfMemoryError:内存溢出异常,产生对象太多,内存不够>不要在循环体重创建大量对象,或对象及时回收,增大初始化堆:-Xms 增加最大值:-Xmx

NoClassDefFoundError:找不到相应的类错误,缺乏当前引用类的jar或jar版本不对->找到jar并放入 classpath中或找到合适的版本

ConcurrentModificationException:并发修改异常,在集合迭代时修改里面的元素->在选代时不要修改集合或用并发集合做遍历(如:ConcurrentHashMap)

NoSuchMethodError:类里找不到相应的方法,一般是iar版本不对,当前引用的jar版本中没有这个方法->检查jar版本是否正确

UnsupportedClassVersionError:版本不支持错误,编译dass的idk和运行时候的idk版本不一致或比较高>将低饭本换成高版本

StackOverflowError:栈溢出错误,一般是函数的死循环,或递归调用无法退出->检查死循环的代码,或让递归有退出值,或加大栈初始化参数

,