【总结】使用异常机制的技巧(欢迎补充)

目前, 存在着大量有关如何恰当地使用异常机制的争论。有些程序员认为所有的已检查异常都很令人厌恶;还有一些程序员认为能够拋出的异常量不够。我们认为异常机制(甚至是已检查异常)有其用武之地。下面给出使用异常机制的几个技巧。
1、异常处理不能代替简单的测试
作为一个示例, 在这里编写了一段代码, 试着上百万次地对一个空栈进行退栈操作。在实施退栈操作之前, 首先要查看栈是否为空。

if (!s.empty()) s.popO;
//接下来,强行进行退栈操作。然后, 捕获 EmptyStackException 异常来告知我们不能这样做。
try{
	s.popO;
}
catch (EmptyStackException e){
}

    在测试的机器上, 调用 isEmpty 的版本运行时间为 646 毫秒。捕获 EmptyStackException 的版
本运行时间为 21 739 毫秒。
   可以看出,与执行简单的测试相比, 捕获异常所花费的时间大大超过了前者, 因此使用
异常的基本规则是:只在异常情况下使用异常机制。
2、不要过分地细化异常
很多程序员习惯将每一条语句都分装在一个独立的 try语句块中。

PrintStream out;
Stack s;
for (i = 0;i < 100; i++)
{
try
{
n = s.popO;
}
catch (EmptyStackException e)
{
II stack was empty
}
try
{
out.writelnt(n);
}
catch (IOException e)
{
ff problem writing to file
}
}

    这种编程方式将导致代码量的急剧膨胀。首先看一下这段代码所完成的任务。在这里,希望从栈中弹出 100 个数值, 然后将它们存人一个文件中。(别考虑为什么,这只是一个“ 玩具” 例子。)如果栈是空的, 则不会变成非空状态;如果文件出现错误, 则也很难给予排除。出现上述问题后,这种编程方式无能为力。因此,有必要将整个任务包装在一个 try语句块中,这样, 当任何一个操作出现问题时, 整个任务都可以取消。

try
{
for (i = 0; i < 100; i++)
{
n = s.popO ;
out.writelnt(n);
}
}
catch (IOException e)
{
// problem writing to file
}
catch (EmptyStackException e)
{
f
] stack was empty
}

    这段代码看起来清晰多了。这样也满足了异常处理机制的其中一个目标,将正常处理与
错误处理分开。
3. 利用异常层次结构
    不要只抛出 RuntimeException 异常。应该寻找更加适当的子类或创建自己的异常类。
    不要只捕获 Thowable 异常, 否则,会使程序代码更难读、 更难维护。
    考虑受查异常与非受查异常的区别。 已检查异常本来就很庞大,不要为逻辑错误抛出这些异常。(例如, 反射库的做法就不正确。 调用者却经常需要捕获那些早已知道不可能发生的异常。)
    将一种异常转换成另一种更加适合的异常时不要犹豫。例如, 在解析某个文件中的 一 个 整 数 时, 捕 获 NumberFormatException 异 常, 然 后 将 它 转 换 成 IOException 或
MySubsystemException 的子类。
4. 不要压制异常
在 Java 中,往往强烈地倾向关闭异常。如果编写了一个调用另一个方法的方法,而这个
方法有可能 100 年才抛出一个异常, 那么, 编译器会因为没有将这个异常列在 throws 表中产
生抱怨。而没有将这个异常列在 throws 表中主要出于编译器将会对所有调用这个方法的方法
进行异常处理的考虑。因此,应该将这个异常关闭:

public Image loadImage(String s)
{
try
{
// code that threatens to throw checked exceptions
}
catch (Exception e)
{} // so there
}

    现在,这段代码就可以通过编译了。除非发生异常,否则它将可以正常地运行。即使发生了异常也会被忽略。如果认为异常非常重要,就应该对它们进行处理。
5. 在检测错误时,“ 苛刻 ” 要比放任更好
当检测到错误的时候, 有些程序员担心抛出异常。在用无效的参数调用一个方法时,返回一个虚拟的数值, 还是抛出一个异常, 哪种处理方式更好? 例如, 当栈空时,Stack.p0p 是返回一个 null, 还是抛出一个异常? 我们认为:在出错的地方抛出一个 EmptyStackException异常要比在后面抛出一个 NullPointerException 异常更好。
6. 不要羞于传递异常
    很多程序员都感觉应该捕获抛出的全部异常。如果调用了一个抛出异常的方法,例如,FilelnputStream 构造器或 readLine 方法,这些方法就会本能地捕获这些可能产生的异常。其实, 传递异常要比捕获这些异常更好:

public void readStuff(String filename) throws IOException // not a sign of shame!
{
InputStreaa in = new FilelnputStream(filename);
}``

让高层次的方法通知用户发生了错误, 或者放弃不成功的命令更加适宜。

注释: 规则 5、6 可以归纳为“ 早抛出,晚捕获

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值