异常的体系结构
- Error : Error指的是Java虚拟机无法去解决的严重问题,例如StackOverflowError和OOM
- Exception :其它因编程错误或偶然的外在因素导致的一般性问题,例如角标越界、空指针异常
Exception的分类
编译时异常
是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子 类都是运行时异常。
运行时异常
是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求Java程序必须捕获或声明所有编译时异常。
异常处理方式
try-catch
try{
// 代码
}catch(Exception e){
//异常处理
}finally{
//必定会执行的代码
}
案例 1:
public class ExceptionTest {
public static void main(String[] args) {
String str = "abc";
try {
Integer.parseInt(str);
}catch (NumberFormatException e){
System.out.println("在这里去处理异常......");
}
System.out.println("程序继续执行....");
}
}
执行结果
案例2:
public class ExceptionTest {
public static void main(String[] args) {
String str = "abc";
try {
Integer.parseInt(str);
}catch (NumberFormatException e){
System.out.println("在这里去处理异常......");
}catch (Exception e){
System.out.println("使用Exception 处理");
}
System.out.println("程序继续执行....");
}
}
案例3:
小总结:
① 根据案例1和案例2可以看到,当我们处理完异常以后,代码会继续去执行他的流程
② 根据案例1和案例2可以看到,应该是先使用子类的异常进行处理,子类处理不了了,才会使用父类的异常进行处理。
③ 根据案例3可以看到,我们的异常定义的顺序应该是从小到大的
try-catch-finally
案例1:
@Test
public void testExceptionFinally(){
int a = 10;
int b = 0;
try {
System.out.println("a / b" + (a / b));
}catch (ArithmeticException e){
System.out.println("执行算数处理异常");
}finally {
System.out.println("执行finally");
}
System.out.println("程序继续执行");
}
执行结果:
案例2 :
@Test
public void testExceptionFinally(){
int a = 10;
int b = 0;
try {
System.out.println("a / b" + (a / b));
}catch (ArithmeticException e){
System.out.println("执行算数处理异常");
try {
String str = null;
str.length();
}catch (NullPointerException el){
System.out.println("执行空指针异常");
}
}finally {
System.out.println("执行finally");
}
System.out.println("程序继续执行");
}
}
案例3:
@Test
public void testExceptionFinally(){
int a = 10;
int b = 0;
try {
System.out.println("a / b" + (a / b));
}catch (ArithmeticException e){
System.out.println("执行算数处理异常");
String str = null;
str.length();
}finally {
System.out.println("执行finally");
}
System.out.println("程序继续执行");
}
}
案例4:测试有返回值的情况下
@Test
public void testMethod(){
int method = method();
System.out.println(method);
}
public int method(){
try {
int[] arr = new int[10];
System.out.println("arr[10] =>" + arr[10]);
return 1;
}catch (IndexOutOfBoundsException e){
System.out.println("执行角标越界异常");
return 2;
}finally {
System.out.println("执行finally");
return 3;
}
}
执行结果:
小总结:
① 根据以上几个案例,我们可以知道如果写了finally它一定是会被执行的。
② 根据案例2和案例3,如果在catch中还有异常,如果没有做相关的处理会发现,会执行finally但是程序不会继续向下执行,如果做了处理,会继续向下执行
③根据案例4,可以看到,他在进行值返回的时候一定会先执行finally,然后在进行值的返回
④什么时候会用到finally,在释放数据库连接,IO连接,或者网络编程Socket的时候会使用到,也就是说Java虚拟机不能自动进行回收的,需要我们自己进行手动的资源释放
throws
public void throwsTest() throws 要抛出的异常类型{
//Code
}
小总结:
- Throws 还是比较简单的,它只是将异常抛给别人,由别人来处理抛出的异常,它自己不做处理
throw手动抛出异常
可以抛出的异常必须是Throwable或其子类的实例
throw new 异常类对象
用户自定义异常类
在一般情况下,自定义异常都是RuntimeException的子类,自定义异常需要提供serialVersionUID,自定义的异常通过throw抛出,重写相关的构造方法
public class MyException extends RuntimeException{
static final long serialVersionUID = -7034897190745766939L;
public MyException(){}
public MyException(String msg){
super(msg);
}
}