第9章 违例差错控制
Java违例差错控制的基本原理就是“形式错误的代码不会运行”。
违例差错控制总则:不要去隐藏程序运行中的错误,而是要告诉用户在遇到错误时该怎么办。
一、Throwable类和Exception类
1、 java.lang.Throwable类:对可以作为违例“掷”出的所有东西进行了描述。
1) public class Throwable extends Object implements Serializable
2) 构造方法
ü
Throwable()
ü Throwable(String message)
3) 成员方法
ü Throwable fillInStackTrace()
:
Fills in the execution stack trace.
ü String
getLocalizedMessage()
:
Creates a localized description of this Throwable
.
ü String
getMessage()
:
Returns the error message string of this throwable object.
ü String
toString()
:
Returns a short description of this throwable object.
ü void
printStackTrace()
:
Prints this Throwable
and its backtrace to the standard error stream.
ü void
printStackTrace(PrintStream s)
:
Prints this Throwable
and its backtrace to the specified print stream.
ü void
printStackTrace(PrintWriter s)
:
Prints this Throwable
and its backtrace to the specified print writer.
2、 java.lang.Exception类
1) public class Exception extends Throwable
2) 构造方法
ü
Exception()
ü Exception(String message)
二、 抛出违例
1、 在异常发生时,应中止方法或作用域的继续,你没有办法解决这个异常,必须抛出一个异常。
2、 基本违例的构造方法:
1) 默认构建器,
2) 使用一个字串自变量
3、 抛出一个基本违例
1) 方法1:throw new NullPointerException();
2) 方法2:throw new NullPointerException("t = null");
4、 抛出一个违例时:
1) 在内存“堆”里来创建一个违例对象。
2) 停止当前执行路径,然后从当前的环境中释放出违例对象的句柄。
3) 违例控制机制接管一切,并开始查找一个恰当的地方,用于继续程序的执行。
三、 违例的捕获
1、 违例控制器
try {
// Code that might generate exceptions
} catch(Type1 id1) {
// Handle exceptions of Type1
} catch(Type2 id2) {
// Handle exceptions of Type2
2、 违例的声明
1) 如果方法产生违例必须声明
2) 方法名 throws异常名1,异常名2{}
3) 可以声明一个并没有真正抛出的违例
3、 捕获所有违例
try{
}catch(Exception e) { }
例:ExceptionMethods.java
4、 重新“掷”出违例
try{
}catch(Type1 id1) {
//
throw id1;
重新“掷”出一个不同的违例;
}
例:Rethrowing.java,RethrowNew.java
四、 标准Java违例
1、 hrowable对象有两种常规子类(Error类代表编译期和系统错误,Exception类是可以从任何标准Java库的类方法中“掷”出的基本类型)我们一般不必特意捕获它们(除在特殊情况以外)。
2、 方法抛出RuntimeException违例,不需要声明。假若一个RuntimeException获得到达main()的所有途径,同时不被捕获,那么当程序退出时,会为那个违例调用printStackTrace()。
五、 创建自己的违例
1、 建自己的违例类,必须从一个现有的违例类型继承——最好在含义上与新违例近似。
例:
六、 违例的限制
1、子类覆盖父类的一个方法时,只能产生比父类中该方法定义的违例少的违例。对违例的限制并不适用于构建器。
2、衍生类构建器必须在自己的违例规范中声明所有基础类构建器违例。
例:
七、用finally清除
1、 无论是否“掷”出一个违例,finally从句都会执行。
try {
// 要保卫的区域:
// 可能“掷”出A,B,或C的危险情况
} catch (A a1) {
// 控制器 A
} catch (B b1) {
// 控制器 B
} catch (C c1) {
// 控制器 C
} finally {
// 每次都会发生的情况
}
2、 用finally做什么
例:OnOffSwitch.java,WithFinally.java,AlwaysFinally.java
3、 缺点:丢失的违例
例:LostMessage.java
八、 构造方法
构造方法一旦产生违例,会正确地进行清除吗?例:Cleanup.java
九、 违例匹配
1. “掷”出一个违例后,违例控制系统会按当初编写的顺序搜索“最接近”的控制器。一旦找到相符的控制器,就认为违例已得到控制,不再进行更多的搜索工作。
2. 在违例和它的控制器之间,并不需要非常精确的匹配。一个衍生类对象可与基础类的一个控制器相配。例:Human.java
十、 违例准则
用违例做下面这些事情:
(1) 解决问题并再次调用造成违例的方法。
(2) 平息事态的发展,并在不重新尝试方法的前提下继续。
(3) 计算另一些结果,而不是希望方法产生的结果。
(4) 在当前环境中尽可能解决问题,以及将相同的违例重新“掷”出一个更高级的环境。
(5) 在当前环境中尽可能解决问题,以及将不同的违例重新“掷”出一个更高级的环境。
(6) 中止程序执行。
(7) 简化编码。若违例方案使事情变得更加复杂,那就会令人非常烦恼,不如不用。
(8) 使自己的库和程序变得更加安全。这既是一种“短期投资”(便于调试),也是一种“长期投资”(改善应用程序的健壮性)