java基础:异常

来源:互联网 发布:爱青岛软件 编辑:程序博客网 时间:2024/06/11 13:33

异常

现有的程序开发技术和测试技术无法确保程序中不存在错误,很多错误不是程序编译时出现(也就是代码错误),而是在运行时由于各种原因(突然断网、文件不存在了)产生的。

几个概念

编译错误:编译阶段语法检查,代码书写不满足语法规则。

运行时错误:指令执行条件的错误,语义错误

逻辑错误:设计不满足要求,未能得到期望结果。

异常:程序在运行时出现的错误。(这里的运行时错误这一概念泛指运行期间发生的错误,与javaRuntimeException类所涵盖的范畴不同,后者仅仅是前者的一个子集)

异常分类:(Java提供了Throwable类,只有Throwable类或其子类的对象,才能被虚拟机或throw语句抛出,并被catch语句捕获;Throwable类有两个子类:ErrorException刻画了不同程度的异常)

  • Error:比较严重的灾难性错误(不可捕获,任其报错)。如:OutOfMemoryError(内存不足)、ThreadDeathIOErrorLinkageError(库链接错误)等。这些异常发生时,JVM一般会选择线程终止

  • Exception:程序本身可以处理的异常(可捕获)。分为以下两种

      • 运行时异常:RuntimeException类及其子类异常,JVM正常操作期间抛出的异常,不需要事先声明可不捕获JVM会接管RuntimeExceptionand its subclasses are uncheckedexceptions.Unchecked exceptions donotneed to be declared in a method or constructor'sthrowsclause if they can be thrown by the execution of the method orconstructor and propagate outside the method or constructorboundary.)如:ArithmeticException(算术异常)、BufferOverflowException(缓冲区上益)、BufferUnderflowExceptionNullPointerException(空指针)。

      • 非运行时异常:RuntimeException以外的异常。必须用catch子句或throws子句指明可能抛出何种异常,否则编译不通过。如:IOExceptionIO异常)、AWTExceptionAWT异常)、InterruptedException(中断异常)、TimeoutException(超市异常)

这是别人博客上写的,感觉很好:(出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往我们不对他处理罢了。也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。如果不想终止,则必须扑捉所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常,或者是通过对异常的处理显式的控制程序退出。

Java异常处理机制

  1. java将程序中运行时出现的各种错误统一处理成“异常对象”,冰箱外抛出;

  2. 捕获并处理这个异常对象,处理策略是:处理或 声明

    • 处理:用try-catch机制实现;用try监控可能出现异常的代码段,用catch捕获和处理异常;

    • 声明:就是声明自己不处理,将异常对象抛给它的调用者,用throws机制实现(在方法声明部分用throws指明本方法可能抛出的异常,以提醒调用者务必采取相应的措施)

(借助JVM的支持,java的异常处理与传统处理方式有很大不同。由于字节码在执行前需要由虚拟机将其翻译成二进制代码,然后执行。JVM可以在执行前根据当时状况对执行效果进行预测。若是发生异常,则由虚拟机创建异常对象并抛出)

JVM的工作模式:监控模式和 正常模式

JVM对执行结果预测将会一定程度上影响代码执行效率,因此JVM只对try-catch-finally语句和throws标记的代码段实施监控预测模式。正常模式下,发生的错误只能被Java虚拟机捕获和处理(比如Error和没有捕获的运行时异常哦,将会终止JVM运行)

异常的声明(throws)和外抛(throw

格式

返回类型 方法名(参数列表) throws 异常列表 {方法体}

throw异常对象的引用

实例


import java.io.IOException;import java.util.Scanner;public class Test {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubtry {f();} catch (ArrayIndexOutOfBoundsException e) {// TODO Auto-generated catch blockSystem.out.println("数组下标越界异常");}catch (ArithmeticException e) {// TODO: handle exceptionSystem.out.println("算术异常");}catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage()+"异常");}}public static void f() throws ArithmeticException,ArrayIndexOutOfBoundsException,Exception{int[] x={1,2};int y,z;while(true){System.out.print("请输入一个整数,-1表示结束:");Scanner in=new Scanner(System.in);y=in.nextInt();if(y==-1)break;if(y==2)throw new IOException();// 假如没有声明Exception的话,这里就会编译错误z=x[y]/y;}}}

异常传播

来看段代码:

public class Test {public static void main(String[] args) {a();}static void a(){b();}static void b(){c();}static void c(){int i=5/0;}}运行结果:Exception in thread "main" java.lang.ArithmeticException: / by zeroat test.Test.c(Test.java:36)at test.Test.b(Test.java:33)at test.Test.a(Test.java:30)at test.Test.main(Test.java:27)方法调用顺序:main → a → b → c异常传递顺序:c → b → a → main → JVM(JVM终止)由于ArithmeticException是运行时异常不需要捕获。

注意点

1. 当try语句块中有return语句,finally也将执行

int f(){    try{        return 5;    }finally{        return 10;    }}//此方法返回的是10
2.throw有类似return的强力转向功能,即throw后的语句不执行,并且导致编译无法通过。

3. 重写方法中

class A{ // 假如这两个异常调换,会报B类中的异常不能跟A类中的兼容void f() throws Exception{}}class B extends A{// 也就是说这个方法中的异常必须和上面方法中的相同或是其子类void f() throws IOException{}}




原创粉丝点击