异常的分类
在代码运行时,可能会出现异常种类有很多,为了对不同异常或者错误进行很好的分类管理,Java内部维护了一个异常的体系结构:
注意事项:
-
Error指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽、内部异常等。靠程序本身是无法解决的,所以我们不关注
-
Exception与Error不同,异常产生后程序员可以通过代码进行处理,使程序继续执行
-
异常可能在编译时发生,也可能在程序运行时发生,根据发生的时机不同,可以将异常分为受检查异常和运行时异常
- 受检查异常,也称为编译时异常。从名字我们就能够理解,就是程序在编译的时候发生的异常(程序已经编译通过得到字节码文件了,再由JVM执行过程中出现的错误)
- 运行时异常,指的是在程序执行期间发生的异常
-
程序中语法错误、逻辑错误都不属于上面的Error和Exception
运行时异常
public class Test {
public static void main(String[] args) {
int[] arr = {1,2,3};
System.out.println(arr.length);
int[] arr2 = null;
System.out.println(arr2.length);
System.out.println(arr[10]);
}
}
程序执行结果为:
3
Exception in thread "main" java.lang.NullPointerException
at com.test.Test.main(Test.java:8)
受检查异常
-
嵌套try-catch
public class Test { public static void main(String[] args) { try { try { Class.forName("com.test.Test").newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
-
多重catch
public class Test { public static void main(String[] args) { try { Class.forName("com.test.Test").newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } }
-
throws
public class Test { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class.forName("com.test.Test").newInstance(); } }
自定义异常
自定义的异常可以继承自运行时异常也可以继承自受检查异常。
需要注意的是:
- 如果继承的是运行时异常,那么在使用的时候无需额外处理
- 如果继承的是受检查异常,那么使用的时候需要
try-catch
捕获或者throws
向上抛
继承自运行时异常
public class MyException extends RuntimeException {
static final long serialVersionUID = -70348971907L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
测试代码如下:
public class Test {
public void checkValue(int value) {
if (value < 0) {
throw new MyException("值不能小于0");
}
}
public static void main(String[] args) {
Test test = new Test();
try {
test.checkValue(-1);
} catch (MyException e) {
System.out.println("捕获到异常: " + e.getMessage());
}
}
}
程序执行结果如下:
捕获到异常: 值不能小于0
继承自受检查异常
public class MyException extends Exception {
static final long serialVersionUID = -70348971907L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
测试代码如下:
public class Test {
// 由于MyException是受检查异常,所以这里需要声明throws MyException
public void checkValue(int value) throws MyException {
if (value < 0) {
throw new MyException("值不能小于0");
}
}
public static void main(String[] args) {
Test test = new Test();
try {
test.checkValue(-1);
} catch (MyException e) {
System.out.println("捕获到异常: " + e.getMessage());
}
}
}
程序执行结果如下:
捕获到异常: 值不能小于0
重载与重写的异常
在之前学习重载和重写的区别时,有提到过在抛出异常方面的区别:
抛出异常 | |
---|---|
重载 | 无关 |
重写 | 小于等于 |
意思是对于重载而言,可以根据需要抛出不同的异常;而对于重写而言,子类重写的函数抛出的异常要小于等于父类中该函数抛出的异常。