Java异常及异常块执行次序(try、catch、finally、return)

Java异常:

①使用try-catch-finally处理异常;

②使用throw、throws抛出异常;

③上边为java异常处理5个关键字。

异常是程序在设计时或运行时产生的错误,异常处理是处理异常的过程,一旦异常被处理后,异常就不存在了,因此程序就可以继续运行了。如果异常不被处理,程序就会被强制终止(终止出现异常的业务代码执行)。

在程序运行中,程序的try、catch、finally、return执行次序,就要进行考虑了

①:捕获异常

       try{
           //执行可能产生异常的代码
       }catch (Exception e) {
           //捕获异常,并处理
       }finally{
           //无论是否发生异常,代码总能执行
       }
       //other code
三种情况:

1:try代码块中无异常,try代码执行完成,则不进入不执行catch(跳过),执行finally块,及异常块后的其他代码other code;

2:try代码块中发生异常,try代码执行到有异常处即之后中断,产生异常对象(跟踪堆栈,执行流程),进入catch块(异常类型匹配后处理),后执行finally块,及异常块后的其他代码other code;

3:try代码块中发生异常,产生异常对象,异常类型不匹配,或者不捕获,程序中断运行(不用try和catch块进行处理,代码在异常出停止);

注:finally块语句唯一不执行的情况:异常处理代码catch中执行System.exit(1)退出Java虚拟机 ;

      一段代码可能会发生多种类型的异常,当发生异常,会按顺序查看每个catch语句,并执行第一个与异常类型匹配的catch块,执行后,其他的catch语句将忽略,执行继续执行finally块,及异常块后的其他代码other code。

②:throws声明异常,throw抛出异常
    //声明方法可能要抛出的各种异常(throws 多个之间用,隔开)
   public static int divide1(int x,int y) throws Exception{
       try{
           //...
       }catch (Exception e) {
           //此处自定义,手动抛出异常,对异常进行处理的代码段
           throw new  Exception("Manual throws an exception");
       }finally{
           //...
       }
       return 0;
   }
注:代码抛出异常后,要在方法上声明可能发生的异常

看段代码,会执行出什么结果:

    //主方法
    public static void main(String[] args) {
        System.out.println(divide(20, 4));
        System.out.println(divide(20, 0));
    }
    //除法
    public static int divide(int x,int y){
        int result = 0;
        try{
            result = x / y;
        }catch (Exception e) {
            
        }finally{
            return -1;
        }
        return result;
    }
其实上边代码是不能被编译通过的:

错误1:

Java异常及异常块执行次序(try、catch、finally、return)

在return result;这一行;

Error:(remove) unreachable code(不能执行到的代码,因为finally在return前执行,return -1;所有代码已经结束,代码return result;则不会被执行)

警告1:

Java异常及异常块执行次序(try、catch、finally、return)

警告在finally块上:

finally块{ }中的代码:Warning:finally block does not complete normally(finally块不能正常完成,finally没有执行完毕就return了)

警告2:在注释掉,有错误的return result;行后.

Java异常及异常块执行次序(try、catch、finally、return)

警告在方法第一层局部变量:int result = 0;上:

局部变量result:Warning:(result)The value of the local variable result is not used(局部变量的值未被使用,在同级范围未被使用,可以在使用出定义更内部局部变量替代.)

错误代码//  return result;,注释掉后,代码:

Java异常及异常块执行次序(try、catch、finally、return)

执行结果为:

我是必须执行的finally!
返回结果:-1

java.lang.ArithmeticException: / by zero
at com.test.TryCatchFinally.testReturnFinallySort(TryCatchFinally.java:12)
at com.test.TryCatchFinally.main(TryCatchFinally.java:7)
我是异常处理日志:除数为空异常!/ by zero
我是必须执行的finally!
返回结果:-1

第二个- 1 ,因为,发生除数为0的算数异常(ArithmeticException),在catch中做了,空处理(只打印打印异常信息日志),所有不做业务异常处理,之后执行finally,所以为-1(两次都是它返回的.)

通过下边代码,现在来看看,try、catch、finally、return执行次序:

    public static void main(String[] args) {
       System.out.println("main output result:"+divide1(20, 0));
    }
    public static int divide1(int x,int y) {
       int result = 0;
       try{
           System.out.println("1 Execute the code before");
           result = x / y;
           System.out.println("2 Execute the code after");
       }catch (Exception e) {
           System.out.println("3 Abnormal block execution:"+e.getMessage());
       }finally{
           System.out.println("4 Has been performed");
       }
       return result;
   }
执行结果:

1 Execute the code before
3 Abnormal block execution:/ by zero
4 Has been performed
注:5 返回方法最终执行结果,此处异常处理,只为打印日志,返回result初始值0.

main output result:0

可以看出:

代码顺序为:执行try中要执行的代码,碰到异常,执行try中代码立即停止,进入catch中处理,处理完成后,进入finally中,最后return代码结束(整个代码正常执行);

下边代码为正常执行(不会进catch)

    public static void main(String[] args) {
       System.out.println("main output result:"+divide1(20, 4));
    }
    public static int divide1(int x,int y) {
       int result = 0;
       try{
           System.out.println("1 Execute the code before");
           result = x / y;
           System.out.println("2 Execute the code after");
       }catch (Exception e) {
           System.out.println("3 Abnormal block execution:"+e.getMessage());
       }finally{
           System.out.println("4 Has been performed");
       }
       return result;
   }
输出为:

1 Execute the code before
2 Execute the code after
4 Has been performed
main output result:5

下边为有异常,但不做异常处理代码:

package com.tsXs.exception;
public class TryCatchForCatchFinally {
    public static void main(String[] args) {
        System.out.println("main output result:"+divide1(20, 0));
    }
   public static int divide1(int x,int y) {
       int result = 0;
       try{
           System.out.println("1 Execute the code before");
           result = x / y;
           System.out.println("2 Execute the code after");
       }finally{
           System.out.println("4 Has been performed");
       }
  System.out.println("5 continue codes.");       return result;
   }
}

控制台,输出为:

1 Execute the code before
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.tsXs.exception.TryCatchForCatchFinally.divide1(TryCatchForCatchFinally.java:10)
at com.tsXs.exception.TryCatchForCatchFinally.main(TryCatchForCatchFinally.java:4)
4 Has been performed
注:异常不被catch处理,则异常发生,程序中断运行,之后其他的代码5步和return都将不会被执行。

java异常结构:

Java异常及异常块执行次序(try、catch、finally、return)

Throwable为Exception和Error类的父类

Error为仅靠程序本身无法恢复的严重错误

Exception为由Java应用程序抛出和处理的非严重错误

RuntimeException运行时异常可以不处理,在编程时应该多考虑,尽量的避免发生

RuntimeException之外的其他异常,设计时异常必须处理,还包括自定义业务异常

注:

异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,JVM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。 异常只能用于错误处理,不应该(建议)用来控制程序流程。

注:错误业务纠正,如果您是做业务需求的话,进入catch之后,如果不写入错误业务处理代码(代码效率低),只打印日志,则应该return停止业务,不然的话,catch块后的代码将会一直执行,导致业务出现错误!看以下代码:

	/**
	 * 测试:异常被处理catch后,是否继续执行
	 * */
	public static void testCodeContinue(){
		int i = 8, h = 0,k = 0;
		int j = i + h;
		System.out.println(i+"+"+h+"的和为:" + j);
		try {
			 k = i / h;
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("我是异常处理日志:除数为空异常!"+e.getMessage());
			//return 返回停止业务代码执行
		}finally{
			System.out.println("我是必须执行的finally!");
		}
		System.out.println("我是异常块后的继续代码……");
		int l = i * h;
		System.out.println(i+"*"+h+"的积为:"+l);
	} 



执行结果:

8+0的和为:8
java.lang.ArithmeticException: / by zero
 at com.test.TryCatchFinally.testCodeContinue(TryCatchFinally.java:16)
 at com.test.TryCatchFinally.main(TryCatchFinally.java:5)
我是异常处理日志:除数为空异常!/ by zero
我是必须执行的finally!
我是异常块后的继续代码……
8*0的积为:0

如果出现错误被return,则:

	/**
	 * 测试:异常被处理catch后,是否继续执行
	 * */
	public static void testCodeContinue(){
		int i = 8, h = 0,k = 0;
		int j = i + h;
		System.out.println(i+"+"+h+"的和为:" + j);
		try {
			 k = i / h;
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("我是异常处理日志:除数为空异常!"+e.getMessage());
			//return 返回停止业务代码执行
			return ;
		}finally{
			System.out.println("我是必须执行的finally!");
		}
		System.out.println("我是异常块后的继续代码……");
		int l = i * h;
		System.out.println(i+"*"+h+"的积为:"+l);
	} 

 

执行结果为:

8+0的和为:8
java.lang.ArithmeticException: / by zero
 at com.test.TryCatchFinally.testCodeContinue(TryCatchFinally.java:53)
 at com.test.TryCatchFinally.main(TryCatchFinally.java:7)
我是异常处理日志:除数为空异常!/ by zero
我是必须执行的finally!

这儿也可以看出,finally在return之前执行.此代码,因为return而终止执行!

上一篇:Codeforces Round #442 (Div. 2)


下一篇:C#日期格式化