Java中的异常处理
1、异常的定义
在Java中出现异常有两种情况:
- 在编写代码时会出现飘红,需要进行抛出机制或捕获机制的叫受检异常(如:数据库异常、IO异常等等)。
- 在编写代码时不会有错,而在程序运行时会使程序中断的错误叫做非受检异常(如:空指针异常,数组下标越界异常等等)
2、受检异常的处理
在程序编写时出现的受检异常,如果不进行异常的处理,那么程序的Java文件将不能被JVM编译成class文件,也就不能在Eclipse或IDEA上运行。因此,在程序编写过程中出现的受检异常需要我们进行处理。
处理受检异常的方式有两种:
- 使用 throw关 键字
- 使用 try-catch-finally 代码块
那么下面就来详细的介绍这两种方法是如何实现的。
2.1、使用throw关键字
这种方式的实现格式为以下所示:
返回值 方法名() throw 异常的类型名称{
}
这种处理方式的本质就是:出现异常的方法自己不作处理,而是将异常交给调用该方法的其它成分处理,这就是俗话说的:将困难抛出去,让别人去处理,从而解放自己。
哪就有小伙伴会有疑问了,这样为啥就可以解决问题了,异常只是抛出去了而已,有没有具体的去解决它。这是因为在进行异常抛出以后,如果没有其它成分调用这个出现受检异常的方法时,是不会有错误的(因为没有调用就不会使用该方法了,异常也就不会发生),就算是有其它成分调用,但是在程序运行时,如果没有出现这类异常,那该方法的异常就不会出现,因此JVM会认为你是进行了异常的,该程序也就可以进行正常的编译了。
使用这种方式尽管可以解决代码在编写时出现异常而不能进行编译的问题,但这种方法也有一个很大的弊端:就是在程序进行运行时,一旦真的出现了异常,出现异常的方法会把异常抛出去,而这个异常如果没有进行相应地处理,最后抛给了JVM(Java虚拟机),那么这段程序将会直接在异常处中断,导致后面代码将无法继续执行。
因此这种处理方式在大型项目中是不可取的,既然不可取那就要用到另一种方式了,下面就来介绍处理异常的第二种方式:使用try-catch代码块。
2.2、使用try-catch-finally代码块
这种方式的实现格式是:
try{
//出现异常的代码块
}catch(异常类型1 异常对象1){
//异常处理操作
}catch(异常类型2 异常对象2){
//异常处理操作
}…funally{
//异常的统一出口
}
也可以写成以下方式:
try{
//出现异常的代码
}catch(异常类型1 | 异常类型2 | …|异常类型n 异常对象){
//处理异常的操作
}finally{
//异常的统一出口
}
该方式处理异常的过程是:当 try 中的代码块出现异常时,将会在catch中的异常类型匹配,匹配成功则执行该 catch 中的异常处理操作,匹配不成功则最后还是会抛给JVM,导致程序异常中断。因此在你不知道会出现哪一个类型的异常时,可以将异常放大到 Exception 这一异常类型,因为这个 Exception 类型是所有异常类型的父类型,将出现的任何异常都做同一种处理,这样就不会出现异常没有捕捉成功的情况。
最后在 finally 中的代码块,不管出现了异常,还是没有出现异常,都会执行,因此在大多涉及到资源释放的代码都会放在 finally 里面,保证资源的成功释放,而不会因为程序的异常中断而导致资源没有及时释放,造成资源的占用。
注意:尽管你在 try 中或是在 catch 中的代码块写了 return 这一关键字,也是执行完 finally 中代码才会跳出方法。但是有一种方式会导致 finally 中的代码无法执行,就是在 try 中或者是 catch 写了正常结束程序的语句,那么 finally 中的代码就不会执行。当然正常项目也不会怎么写,了解就好。
//退出程序的语句
System.exit(0);
3、非受检异常处理
上面介绍了受检异常的相关处理操作,也提到了 Exception 类型,而受检异常的直接父类就是 Exception 类型,当然异常还有一种,那就是在异常定义中提到的:非受检异常,而这类异常的直接父类并不是 Exception 类而是 Exception 类的一个子类:RuntimeException 类。
非受检异常在编写时不会出现错误,没有明显的异常提示,因此可以在代码中不需要明确的进行异常处理,但是,在程序运行时如果发生了异常,那就会被JVM捕捉到,从而导致程序异常中断。所以在测试时如果发现有非受检异常记得及时进行捕捉异常的处理。
4、异常的体系结构
异常的体系结构如图所示:
5、自定义异常
在编写项目时,有时候可能需要你自己定义一种异常处理的类型来满足项目的功能,那下面有两种方式可以实现自己定义异常类型:
- 自定义一个类,继承 Exception 类,并重写无参构造方法或一参构造方法,便可以完成自定义异常类型。
- 自定义一个类,继承 RuntimeException 类,并重写无参构造方法或一参构造方法,便可以完成自定义异常类型。
代码演示:
//可以是:继承 Exception 类
class MyException extends Exception{
public MyException(String msg){
super(msg); // 调用Exception中有一个参数的构造
}
};
//或者是:继承 RuntimeException 类
class MyException extends RuntimeException{
public MyException(String msg){
super(msg); // 调用Exception中有一个参数的构造
}
};
自定义异常类型不是很常使用,因此作为了解就好。
好了,关于异常处理的相关知识就介绍到这,希望文章可以帮到你们,谢谢阅读。如果觉得文章写得不错就关注我吧,我会不定期更新关于Java相关知识的博文。