Java异常的分类
Error : 代表了JVM本身的错误,JVM会做出终止线程的动作,我们不作处理
Exception : 异常分为运行时异常
和编译期异常
编译时异常:必须处理,否则程序编译无法通过
RuntimeException:即运行时异常,我们必须修正代码
异常处理语句
try-catch
try:用于监听异常
catch:用于捕获处理异常
捕获单个异常
try{
//程序代码
}catch (ExceptionName e1){
//Catch块
}
多重捕获块
当try中程序发生异常,会按照从上往下
的顺序与catch进行匹配,一旦与其中一个匹配后就不会再与后面的catch进行匹配了,所以,要把范围小的放在前面,范围大的放在后面
!
try{
//程序代码
}catch (异常类型1 异常的变量名1){
......
}catch (异常类型2 异常的变量名2){
......
}catch (异常类型3 异常的变量名3){
......
}
try-catch-finally
1、无论是否发生异常,finally 代码块中的代码总会被执行,常用作清理类型等收尾善后性质的语句
2、在catch中遇到return时,仍然会先执行finally语句,再回来执行对应catch语句中的return语句
try{
......
}catch(异常类型1 异常的变量名1){
......
}catch(异常类型2 异常的变量名2){
......
}finally{
......
}
Further Reading: 异常抛出时Try Catch Finally Return 执行顺序
throws和throw的区别?
throw
用来抛出异常
if(s == null){
throw new NullPointerException();
}
throws
进行异常说明
的关键字。声明这个方法可能会出现这样的异常
public void f(String s) throws NullPointerException { //函数声明异常
if(s == null){
throw new NullPointerException(); //抛出异常
}else{
System.out.println(s);
}
}
Further Reading throw和throws区别是什么?
自定义异常
Java内置的异常类,基本可以满足我们在编程中遇到的大部分异常情况。
此外我们也可以自定义异常类,只需要继承Exception类即可
public class UserDefinedException extends Exception {
public UserDefinedException() {
}
public UserDefinedException(String message) {
super(message);
}
}
public void testMyException() throws UserDefinedException {
if (3 > 2) {
throw new UserDefinedException("说明一下异常的具体问题");
}
}
工作中总结以下几点
1、继承RuntimeException
2、业务异常要有个共同父类,这样业务catch时就可以用父类catch住,不然会一堆catch去枚举
JVM 是如何处理异常的?
在一个方法中如果发生异常,这个方法会创建一个异常对象
,并转交给 JVM。JVM会顺着调用栈去查找看是否有可以处理异常的代码。当JVM发现有可以处理异常的代码时,会把发生的异常传递给它。如果 JVM 没有找到可以处理该异常的代码块,JVM 就会将该异常转交给默认的异常处理器(默认处理器为JVM的一部分),默认异常处理器打印出异常信息并终止应用程序。
该异常对象包含异常名称
,异常描述
以及异常发生时应用程序的状态
。
创建异常对象并转交给JVM的过程称为抛出异常
。
可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做调用栈
。
Further Reading:JVM是如何处理异常的
Java常见异常
异常 | 解释 |
---|---|
java.lang.NullPointerException | 空指针异常。 当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如 |
java.lang.IllegalAccessError | 违法访问错误。 当一个应用试图访问、修改某个类的属性或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。看见了不该看见的 |
java.lang.InstantiationError | 实例化错误。 当一个应用试图通过Java的 new 操作符构造一个抽象类或者接口时抛出该异常. |
java.lang.InstantiationException | 实例化异常。 当试图通过 newInstance() 方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常。 |
java.lang.OutOfMemoryError | 内存不足错误。 当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。 |
java.lang.StackOverflowError | 堆栈溢出错误。 当一个应用递归调用的层次太深而导致堆栈溢出或者陷入死循环时抛出该错误。 |
java.lang.ClassCastException | 强制类型转换异常。 |
java.lang.ClassNotFoundException | 找不到类异常。 |
java.lang.ArithmeticException | 算术条件异常。 譬如:整数除零等。 |
java.lang.NumberFormatException | 数字格式异常。 当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。 |
java.lang.ArrayIndexOutOfBoundsException | 数组索引越界异常。 当对数组的索引值为负数或大于等于数组大小时抛出。 |
java.lang.IndexOutOfBoundsException | 索引越界异常。 当访问某个序列的索引值小于0或大于等于序列大小时,抛出该异常。 |
java.lang.StringIndexOutOfBoundsException | 字符串索引越界异常。 当使用索引值访问某个字符串中的字符,而该索引值小于0或大于等于序列大小时,抛出该异常。 |
java.lang.NoSuchFieldException | 属性不存在异常。 当访问某个类的不存在的属性时抛出该异常。 |
java.lang.NoSuchMethodException | 方法不存在异常。 当访问某个类的不存在的方法时抛出该异常。 |
非受检查异常,受检查异常
非检查异常(unckecked exception):Error 和 RuntimeException 以及他们的子类
检查异常(checked exception):除了Error 和 RuntimeException的其它异常。
非受检查异常 |
---|
NullPointException (空指针) |
NumberFormatException (字符串转换为数字) |
IndexOutOfBoundsException (数组越界) |
ClassCastException (类转换异常) |
ArrayStoreException (数据存储异常,操作数组时类型不一致)等。 |
受检查异常 |
IO 相关的异常 |
ClassNotFoundException |
SQLException 等 |
NoClassDefFoundError 和 ClassNotFoundException 区别?
NoClassDefFoundError |
---|
是一个 Error 类型的异常,是由 JVM 引起的,不应该尝试捕获这个异常 |
引起该异常的原因: |
JVM 或 ClassLoader 尝试加载 某类时在内存中 找不到该类的定义 ,该动作发生在运行期间,即编译时该类存在,但是在运行时却找不到了,可能是变异后被删除了等原因导致 |
ClassNotFoundException |
是一个受检查异常,需要显式地使用 try-catch 对其进行捕获和处理,或在方法签名中用 throws 关键字进行声明。 |
引起该异常的原因: |
1. 当使用 Class.forName , ClassLoader.loadClass 或 ClassLoader.findSystemClass 动态加载类到内存的时候,通过传入的类路径参数没有找到该类,就会抛出该异常; |
2. 另一种抛出该异常的可能原因是某个类已经 由一个类加载器加载 至内存中,另一个加载器又尝试去加载 它。 |