java中的异常处理机制
异常是指程序运行时所发生的非正常情况或错误,java中使用异常能够降低错误处理代码的复杂度,如果不使用异常,就必须检查特定的错误,并在程序中的许多地方去处理它。
1.java的标准异常
Throwable这个java类被用来表示任何可以作为异常被抛出的类,Throwable对象可以分为两种类型,Error和Exception。
Error可以用来表示编译时和系统错误,表示程序在运行期间出现了非常严重的错误,并且该错误是不可恢复的,由于这属于JVM层次的严重错误,因此这种错误会导致程序终止执行。
Exception是可以被抛出的基本类型,表示可恢复的异常,是编译器可以捕捉到的,它包含两种类型,检查异常和运行时异常。检查异常是在程序中经常碰到的异常,比如最常见的IO异常和SQL异常,这种异常都发生在编译阶段,java编译器强制程序去捕获此类型的异常,即把可能会出现异常的代码块放在try块中,把对异常的处理放在catch块中。
运行时异常不同于检查异常,当出现这种异常时,会由JVM来处理,最常见的运行时异常包括NullPointerException(空指针异常),ClassCastException(类型转换异常),ArrayIndexOutOfBoundsException(数组越界异常),ArrayStoreException(数组存储异常),BufferOverFlowException(缓冲区溢出异常),ArithmeticException(算术异常)等。出现运行时异常后,系统会把异常一直往上层抛出,直到遇到处理代码为止,若没有处理块,则抛到最上层,如果是多线程,就用Thread.run()方法抛出,如果是单线程,就用main()方法抛出。抛出之后,如果是多线程,这个线程就退出了,如果是主线程,整个程序也就退出了。
2.抛出异常的三种方式
2.1 系统自动抛出异常
@Test
public void test1(){
int a=8;
int b=0;
System.out.println(a/b);
}
运行后抛出异常:java.lang.ArithmeticException: / by zero
2.2 throw
throw是语句抛出一个错误,一般是在代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常。在使用new创建了异常对象之后,此对象的引用将传递给throw。
@Test
public void test2(){
String s="abc";
if(s.equals("abc")){
throw new NumberFormatException();
}else{
System.out.println(s);
}
}
运行后抛出异常:java.lang.NumberFormatException。
2.3 throws
当某个方法可能会抛出异常时,用throws声明可能抛出的异常,然后上交给它的方法程序处理。
public static void f() throws NumberFormatException{
System.out.println("try语句块先执行");
String s="abc";
System.out.println(Double.parseDouble(s));
}
public static void main(String[] args){
try{
f();
}catch(NumberFormatException e){
System.err.println("非数据类型不能强制类型转换。");
}
}
运行后输出:
try语句块先执行 非数据类型不能强制类型转换。
3.捕获异常
java程序在抛出异常后,首先使用new在堆上创建异常对象,然后当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用,之后处理机制接管程序,并且开始寻找异常处理程序来继续执行程序。
如果在方法内部抛出异常,这个方法将在抛出异常的过程中结束,要是不希望方法就此结束,可以在方法内设置一个try块来捕获异常。抛出的异常必须在异常处理程序中得到处理,异常处理程序紧跟在try块之后,以关键字catch表示。异常处理程序的任务就是将程序从错误状态中恢复,以使程序要么换一种方式运行,要么继续运行下去。
import org.junit.Test;
class Exception1 extends Exception{
}
public class ExceptionTest {
public int testFinally(){
try{
System.out.println("try执行");
throw new Exception1();
}catch(Exception1 e){
System.out.println("catch");
return 0;
}finally{
System.out.println("execute finally");
return 1;
}
}
@Test
public void test(){
int result=testFinally();
System.out.println(result);
}
}
finally块的作用是为了保证无论出现什么情况,finally块里的代码一定会执行。 如果try-finally和catch-finally中都有return,那么finally块里的return语句将会覆盖别处的return语句,最终返回到调用者那里的都是finally中return值。(其他正常执行,但是return由finally中的return覆盖。)
程序运行结果:
try执行 catch execute finally 1
在使用异常处理时,还需注意java异常处理用到了多态的概念,如果在异常处理过程中,先捕获了基类,然后再捕获子类,那么捕获子类的代码块将永远不会被执行,因此在进行异常捕获时,正确的应该是先捕获子类,再捕获基类的异常信息。
try{
//
}catch(SQLException e1){
//
}catch(Exception e2){
//
}
浙公网安备 33010602011771号