灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:3501回复:0

黑马程序员 java异常理解

楼主#
更多 发布于:2013-02-20 13:13

异常
现有的程序开发技术和测试技术无法确保程序中不存在错误,很多错误不是程序编译时出现(也就是代码错误),而是在运行时由于各种原因(突然断网、文件不存在了)产生的。
几个概念
编译错误:编译阶段语法检查,代码书写不满足语法规则。
运行时错误:指令执行条件的错误,语义错误。
逻辑错误:设计不满足要求,未能得到期望结果。
异常:程序在运行时出现的错误。(这里的运行时错误这一概念泛指运行期间发生的错误,与java的RuntimeException类所涵盖的范畴不同,后者仅仅是前者的一个子集)
异常分类:(Java提供了Throwable类,只有Throwable类或其子类的对象,才能被虚拟机或throw语句抛出,并被catch语句捕获;Throwable类有两个子类:Error和Exception刻画了不同程度的异常)
Error:比较严重的灾难性错误(不可捕获,任其报错)。如:OutOfMemoryError(内存不足)、ThreadDeath、IOError、LinkageError(库链接错误)等。这些异常发生时,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(缓冲区上益)、BufferUnderflowException、NullPointerException(空指针)。
非运行时异常:RuntimeException以外的异常。必须用catch子句或throws子句指明可能抛出何种异常,否则编译不通过。如:IOException(IO异常)、AWTException(AWT异常)、InterruptedException(中断异常)、TimeoutException(超市异常)
这是别人博客上写的,感觉很好:(出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往我们不对他处理罢了。也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。如果不想终止,则必须扑捉所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常,或者是通过对异常的处理显式的控制程序退出。)
Java异常处理机制
java将程序中运行时出现的各种错误统一处理成“异常对象”,冰箱外抛出;
捕获并处理这个异常对象,处理策略是:处理或 声明
处理:用try-catch机制实现;用try监控可能出现异常的代码段,用catch捕获和处理异常;
声明:就是声明自己不处理,将异常对象抛给它的调用者,用throws机制实现(在方法声明部分用throws指明本方法可能抛出的异常,以提醒调用者务必采取相应的措施)
(借助JVM的支持,java的异常处理与传统处理方式有很大不同。由于字节码在执行前需要由虚拟机将其翻译成二进制代码,然后执行。JVM可以在执行前根据当时状况对执行效果进行预测。若是发生异常,则由虚拟机创建异常对象并抛出)
JVM的工作模式:监控模式和 正常模式
JVM对执行结果预测将会一定程度上影响代码执行效率,因此JVM只对try-catch-finally语句和throws标记的代码段实施监控预测模式。正常模式下,发生的错误只能被Java虚拟机捕获和处理(比如Error和没有捕获的运行时异常哦,将会终止JVM运行)
异常的声明(throws)和外抛(throw)
格式
返回类型 方法名(参数列表) throws 异常列表 {方法体}
throw异常对象的引用
实例
 
[java]  
import java.io.IOException;  
import java.util.Scanner;  
  
public class Test {  
  
    /**
     * @param args
     */  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        try {  
            f();  
        } catch (ArrayIndexOutOfBoundsException e) {  
            // TODO Auto-generated catch block  
            System.out.println("数组下标越界异常");  
        }catch (ArithmeticException e) {  
            // TODO: handle exception  
            System.out.println("算术异常");  
        }catch (Exception e) {  
            // TODO: handle exception  
            System.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;  
        }  
    }  
}  
 
异常传播
来看段代码:
[java]
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 zero  
    at 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也将执行
[java]  
int f(){  
    try{  
        return 5;  
    }finally{  
        return 10;  
    }  
}//此方法返回的是10  
2.throw有类似return的强力转向功能,即throw后的语句不执行,并且导致编译无法通过。
3. 重写方法中www.atcpu.com
 
[java]  
class A{ // 假如这两个异常调换,会报B类中的异常不能跟A类中的兼容  
    void f() throws Exception{  
          
    }  
}  
class B extends A{  // 也就是说这个方法中的异常必须和上面方法中的相同或是其子类  
    void f() throws IOException{  
          
    }  
}  
 

喜欢0 评分0
游客

返回顶部