派生于 RuntimeException 的异常包含下面几种情况:
•错误的类型转换。
•数组访问越界 i
•访问 null 指针
不是派生于 RuntimeException 的异常包括:
•试图在文件尾部后面读取数据。
•试图打开一个不存在的文件。
•试图根据给定的字符串查找 Class 对象, 而这个字符串表示的类并不存在,,
如果出现 RuntimeException 异常, 那么就一定是你的问题” 是一条相当有道理的规则。 应该通过检测数组下标是否越界来避免 ArraylndexOutOfBoundsException 异常;应该通过在 使用变量之前检测是否为 null 来杜绝 NullPointerException 异常的发生
public void read(String filename)
{
try
{ InputStream in = new Filei叩utStream(filename);
int b;
while ((b = in.read()3 != -1 ) { process input } }
catch (IOException exception)
{
exception.printStackTrace();
}
需要注意的是,try语句中的大多数代码都很容易理解: 读取并处理字节, 直到遇到文 件结束符为止。正如在 Java API 中看到的那样, read方法有可能拋出一个 IOException 异常。 在这种情况下,将跳出整个 while 循环,进入 catch 子旬,并生成一个栈轨迹。对于一个普通 的程序来说, 这样处理异常基本上合乎情理
try {
access the database
} catch (SQLException e) Throwable se = new ServletException(“database error”);
se.initCause(e);
throw se;
当捕获到异常时,就可以使用下面这条语句重新得到原始异常: Throwable e = se.getCause();
强烈建议使用这种包装技术。这样可以让用户抛出子系统中的高级异常,而不会丢失原始异 常的细节。
如果在一个方法中发生了一个受查异常, 而不允许抛出它, 那么包装技术就十分 有用。我们可以捕获这个受查异常,并将它包装成一个运行时异常。
• Throwable(Throwable cause) 1.4
• Throwable(String message, Throwable cause) 1.4 用给定的“ 原因” 构造一个 Throwable 对象。
• Throwable initCause(Throwable cause) 1.4 将这个对象设置为“ 原因”。如果这个对象已经被设置为“ 原因”, 则抛出一个异常。 返回 this 引用。
• Throwable getCause() 1.4 获得设置为这个对象的“ 原因” 的异常对象。如果没有设置“ 原因”, 则返回 null
• StackTraceElement[] getStackTrace() 1.4 获得构造这个对象时调用堆栈的跟踪。
• void addSuppressed(Throwable t) 7 为这个异常增加一个“ 抑制” 异常。这出现在带资源的 try语句中, 其中 t 是 dose方 法抛出的一个异常。
• Throwable[] getSuppressed() 7 得到这个异常的所有“ 抑制” 异常。一般来说,这些是带资源的 try语句中 close 方法 拋出的异常。
7.3 使用异常机制的技巧
1.异常处理不能代替简单的测试
可以看出,与执行简单的测试相比, 捕获异常所花费的时间大大超过了前者, 因此使用 异常的基本规则是:只在异常情况下使用异常机制。
- 不要过分地细化异常
这段代码看起来清晰多了。这样也满足了异常处理机制的其中一个目标,将正常处理与 错误处理分开
3.利用异常层次结构
将一种异常转换成另一种更加适合的异常时不要犹豫。例如, 在解析某个文件中 的 一 个 整 数 时, 捕 获 NumberFormatException 异 常, 然 后 将 它 转 换 成 IOException或 MySubsystemException 的子类。
-
不要压制异常
100年一遇的异常就不要对他进行处理。直接关闭。. -
在检测错误时, “ 苛刻” 要比放任更好
在出错的地方抛出一个 EmptyStackException 异常要比在后面抛出一个 NullPointerException异常更好。 不要为了程序能运行而造假程序。 -
不要羞于传递异常
让高层次的方法通知用户发生了错误, 或者放弃不成功的命令更加适宜。
断言机制允许在测试期间向代码中插入一些检査语句。当代码发布时,这些插人的检测 语句将会被自动地移走。
这两种形式都会对条件进行检测, 如果结果为 false, 则抛出一个 AssertionError 异常。 在第二种形式中,表达式将被传人 AssertionError 的构造器,并转换成一个消息字符串。
需要注意的是, 在启用或禁用断言时不必重新编译程序。启用或禁用断言是类加载器 ( class loader) 的功能。当断言被禁用时, 类加载器将跳过断言代码, 因此,不会降低程序运 行的速度。
java -enableassertions MyApp
也可以用选项-disableassertions 或 -da 禁用某个特定类和包的断言: java -ea:… -da:MyClass MyApp 有些类不是由类加载器加载, 而是直接由虚拟机加载。可以使用这些开关有选择地启用 或禁用那些类中的断言。 然而, 启用和禁用所有断言的 -ea 和 -da 开关不能应用到那些没有类加载器的“ 系统类” 上。对于这些系统类来说, 需要使用-enablesystemassertions/-esa 开关启用断言。
什么时候应该选择使用断言呢? 请记住下面几点:
•断言失败是致命的、 不可恢复的错误。
•断言检查只用于开发和测阶段(这种做法有时候被戏称为“ 在靠近海岸时穿上救生衣, 但在海中央时就把救生衣抛掉吧”) 。
多语句抓取多个异常的时候碰到第一个异常,程序自动中断。
异常要是继承父类异常,那么子类异常在写抓取异常时候要写在父类异常前面,程序才不会报错。