Java异常Exception(一)

来源:互联网 发布:dtxmania软件下载 编辑:程序博客网 时间:2024/05/23 20:06

1,软件开发过程中为了保证软件的健壮性,必须对各种可能存在的异常情况进行检测并进行有效的处理。合理的情况下,真正的业务代码占用总代码量的1/3左右。

2,Java中定义了一套异常处理机制Exception。Java中的异常是通过try{}catch(){} 和trow 语法来完成,之所以这样是为了将业务功能代码集中在try块中,将异常处理代码集中在catch块中,实现代码的良好结构。

public classExceptionTest {   public static void main(String args[]){      try{         System.out.println("s1");         int i = 1/0;         System.out.println("s2");      }catch(ArithmeticExceptione){         System.out.println("s3");      }catch(Exceptione){         System.out.println("s4");      }finally{         System.out.println("s5");      }      System.out.println("s6");   }}


如上输出

s1

s3

s5

s6

示例中通过除数为0抛出一个ArithmeticException,代码块在遇到异常后,会跳过后面的代码只到遇到catch语句,所以s2输出语句没有执行。如果当前函数没有catch语句,则整个函数向上级调用语句抛出异常,直到启动函数main,并终止程序。catch语句可以有多层捕捉,只会在第一个匹配的catch块捕捉,后面的不会再执行,如s4语句没有输出。在finally块中的语句一定会执行,即使在try块中有return语句,finally也会执行,除非一下情形:

1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。

此外一定要注意,如果在catch语句中有继续向外层调用抛出异常的情况,finally中最好不要用return返回语句,因为,如果finally是在异常语句执行最后一步执行的语句,finally中有return语句,finally前面的catch语句中的trow Exception不能被外层调用捕捉。

如:

public class ExceptionTest2 {public void fun1(){try{fun2();} catch (Exception e){System.out.println("fun1()-catch");} finally {System.out.println("fun1()-finally");}}public void fun2() throws Exception{try{int i = 1 / 0;} catch (Exception e){System.out.println("fun2()-catch");throw e;} finally {System.out.println("fun2()-finally");return;}}public static void main(String args[]){new ExceptionTest2().fun1();}}
如上输出

fun2()-catch
fun2()-finally
fun1()-finally

3, catch捕捉的异常遵循类继承定义,并不一定是精确匹配,catch后的Exception可以是抛出异常的类或者父类。如果要捕捉到所有的异常,只需要在catch中捕捉Exception就可以了。

4, 在之类继承父类中,对于覆盖父类的函数,必须不能多于父类函数抛出的异常。子类抛出的异常类型可以是父类函数异常的子类。

class Aextends Exception{}class Bextends A{}class Dextends Exception{}interface I {   void f() throws A;   void g() throws D;   void h();}interface II {   void g() throws A;}abstract classAC implementsI{   public AC()throws A{   }}class C extendsAC implementsII{   public C()throws A, D{     // --(1)   }   public void f() throws B{    // --(2)   }   public void h() {           // --(3)   }   public void g() {             // --(4)   }}


如上:

(1)父类的构造函数抛出A,但是子类抛出了A,D。其中A是必须的,因为构造子类C时会调用父类AC的构造函数,AC的构造函数抛出异常A,所以C的构造函数一定需要抛出A,同时可以抛出D因为构造函数对父类构造函数不构成覆盖。

(2)抛出的异常一定是异常类A或者其子类,并且最多只能一个异常,应为f()覆盖了父类的该函数之抛出了异常A。

(3)该出不能抛出异常,如果在定义变量时用AC的引用指向了C的对象,如果此时调用函数h(),则调用处可能因为没有为异常做好准备对应类。

(4)此处函数g()在两个父类中抛出不同的异常,如果该出要抛出异常,该异常必须是两个父类抛出异常的交集,而交集为空,只能不抛出异常了,否则抛出任何异常都会导致系统无法编译通过。


原文链接

以上笔记,如有错误请指正


1 0
原创粉丝点击