------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. 使用 throws 抛出异常
2. 使用 try-catch 语句捕获异常
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();
}
}
}