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:
在return result;这一行;
Error:(remove) unreachable code(不能执行到的代码,因为finally在return前执行,return -1;所有代码已经结束,代码return result;则不会被执行)
警告1:
警告在finally块上:
finally块{ }中的代码:Warning:finally block does not complete normally(finally块不能正常完成,finally没有执行完毕就return了)
警告2:在注释掉,有错误的return result;行后.
警告在方法第一层局部变量:int result = 0;上:
局部变量result:Warning:(result)The value of the local variable result is not used(局部变量的值未被使用,在同级范围未被使用,可以在使用出定义更内部局部变量替代.)
错误代码// return result;,注释掉后,代码:
执行结果为:
我是必须执行的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异常结构:
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而终止执行!