------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------    

 

异常

    异常就是Java程序在运行过程中出现的导致程序无法正常运行的错误。

Java 中异常继承体系,顶层的类

    java.lang.Throwable

    java.lang.Exception 所有异常的超类

       RuntimeException 运行时异常可以不处理

       RuntimeExceptioin非运行时异常必须捕获处理

    java.lang.Error 所有错误的超类

 

异常处理机制

    当程序中抛出一个异常后,程序从程序中导致异常的代码处跳出,java虚拟机检测寻找和 try关键字匹配的处理该异常的 catch块,如果找到,将控制权交到 catch块中的代码,然后继续往下执行程序,try 块中发生异常的代码不会被重新执行。如果没有找到处理该异常的 catch 块,在所有的 finally 块代码被执行和当前线程所属的ThreadGroup uncaughtException 方法被调用后,遇到异常的当前线程被中止。

 

异常处理

    Java语言中,使用 throw 关键字来引发异常。

    对异常处理的两条途径为:

  1. 1.  使用 throws 抛出异常

  2. 2.  使用 try-catch 语句捕获异常

  3. n  try-catch

try {

    可能出现异常的代码

} catch(Exception e) {

    异常处理代码

}

  • 多个 catch

每个 try 语句块可以伴随一个或多个 catch 语句,用于处理可能产生的不同类型的异常。catch 捕获的异常类型由上至下的捕获异常类型的顺序应是子类到父类的。子类型异常在前,父类型异常在后,这样的顺序依次捕获。否则编译不通过。

  • finally 语句

为异常处理提供一个统一的出口,使得在控制流程跳转到程序其它部分以前,能够对序的状态作统一管理。无论 try 所指定的程序块中是否抛出异常,finally 所指定的代码都要被执行。通常在finally 语句中可以进行资源的释放工作。

 

  • throw 关键字

写在方法内部,抛出异常,后面写 new 异常对象

    当程序发生错误而无法处理的时候,会抛出对应的异常对象,或用于自行抛出异常。

  • throws 关键字

写在方法声明上,告诉调用者处理异常,后面写异常类类名

    方法中可能会因某些错误而引发异常,希望调用者处理,声明方法会抛出异常。

method()throws Exception { // 声明异常,让调用者处理

    throw new Exception() // 抛出异常

}

  • 重写方法时的throws

    如果使用继承时,在父类的某个方法上声明 throws 某些异常,而在子类中重新定义该方法时,

可以:

不处理异常(重新定义时不设定throws

可仅 throws 父类中声明的部分异常

throws 父类方法中抛出异常的子类异常

不可以:

throws 出额外的异常

throws 父类方法中抛出异常的父类异常

概括为:父类方法中抛出异常,子类重写可抛可不抛;父类不抛,子类不能抛出。

 

异常的分类

    ——运行时异常RuntimeException ,又称非检测异常

    直接或间接继承RuntimeException 的异常。不受编译器检查与处理或声明规则的限制,在发生此类异常时,不一定非要采取处理操作,编译器不会检查是否解决异常。

    ——非运行时异常又称可检测异常,编译时异常

    是指除了RuntimeException 以外的其他异常,是程序有逻辑错误。可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译。

    Java编译器要求方法必须声明抛出可能发生的非运行时异常,但是不要求必须声明抛出未被捕获的运行时异常。

 

——常见的运行时异常:

    IllegalArgumentException 不合法参数异常:向方法传递一个不合法或不正确参数

NullPointerException空指针异常:当操作一个空引用时会出现此异常

    NumberFormatException 数字格式化异常:试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常

    ClassCastException 类型转换异常:强制类型转换类型不匹配时出现此异常

    ArrayIndexOutOfBoundsException 数组下标越界异常:当使用一个不存在的数组下标时出现此异常。

    ArithmeticException 数学异常:当出现异常的运算条件时出现此异常

——常见的非运行时异常:

    SQLException 提供关于数据库访问错的异常

    IOException 当发生某种 I/O 异常时,抛出此异常

    ClassNotFoundException 当应用程序试图使用 Class 类中的 forName 方法、loadClass 方法时,抛出该异常

 

Throwable 中的方法

    getMessage() // 获取异常信息,返回字符串

    toString() // 获取异常类名和异常信息,返回字符串

    printStackTrace() // 获取异常类名和异常信息及出现的位置,输出执行堆栈信息

    printStackTrace(PrintStream s) // 将异常内容保存在日志文件中

 

自定义异常

    为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常。

    继承 Exception 自定义异常,定义好自定义异常后,可以通过IDE生成相应构造方法。

    class 自定义异常类名 extendsException {

       …

}

 

编译时期异常和运行时期异常的区别:

    编译时期异常:抛出的异常类,不是RuntimeException类或者其子类

    调用者,调用一个抛出异常的方法,如果不处理,编译失败

    异常是编译器最后检测的问题

 

    运行时期异常:抛出的异常类,是RuntimeException类和其子类

    抛出的是运行时期异常,凡是方法内部抛出的异常是运行时期,方法的声明上,无需throws,对应方法的调用者,就不需要处理异常。

 

    运行时期异常的设计思想:

    运行时期异常,在程序的运行中,是不能发生的,如果真的发生了,请程序人员停止程序,修改源代码,运行时期异常一旦发生,后面的代码就没有运行的必要了。

 

finally 的特点及作用

    特点:被 finally 控制的语句体一定会执行,在return 返回值之前执行

    特殊情况:在执行finally之前jvm 退出(如System.exit(0)),线程死亡,关闭CPU

    作用:释放资源(I/O 操作和数据库操作)

 

packagecn.itcast;

 

/*

 * finally 语句块不应该出现应该出现return

 * return ret 最好是其他语句来处理相关逻辑

 *

 * 正确运行结果是:

 *  i= 2

 *  i= 1

 *  testEx2, catch exception

 *  testEx2, finally; return value = false

 *  testEx1, finally; return value = false

 *  testEx, finally; return value = false

 */

publicclass TestException {

 

    public TestException() {

    }

 

    boolean testEx() throws Exception {

       booleanret = true;

       try {

           ret = textEx1(); // 接收返回值false

       } catch (Exception e) {

           System.out.println("testEx,cathch exception");

           ret = false;

           throwe;

       } finally {

           System.out.println("testEx,finally; return value= " + ret); //false

           returnret; // false

       }

    }

 

    boolean textEx1() throws Exception {

       booleanret = true;

       try {

           ret = textEx2(); // 接收返回值false

           if (!ret) {

              returnfalse;

           }

           System.out.println("testEx1,at the end of try");

           returnret;

       } catch (Exception e) {

           System.out.println("testEx1,cathch exception");

           ret = false;

           throwe;

       } finally {

           System.out.println("testEx1,finally; return value= " + ret); //false

           returnret; // try块中已有返回值,此为无效语句

       }

    }

 

    boolean textEx2() throws Exception {

       booleanret = true;

       try {

           intb = 12;

           intc;

           for (inti = 2; i>= -2; i--) {

              c= b / i;

              System.out.println("i=" + i);// 2, 1

           }

           returntrue; // 上面发生异常,此句未执行

       } catch (Exception e) {

           System.out.println("testEx2,catch exception");

           ret = false;

           throwe;

       } finally {

           System.out.println("testEx2,finally; return value= " + ret); //catch语句中赋值false

           returnret; // false

       }

    }

 

    publicstaticvoid main(String[] args) {

       TestExceptiontestException1 = newTestException();

       try {

           testException1.testEx();

//         System.out.println(testException1.testEx());// false

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

 

}