Java 异常处理的优劣

Java编程中的异常处理是一个很常见的话题了,几乎任何一门介绍性的Java课程都会提到异常处理。不过,我认为很多人其实没有真正掌握正确处理异常情况的方法和策略,最多也就不过了解个大概,知道概念。我想对三种不同程度和质量的Java异常处理进行了讨论,所阐述的处理异常的方式按手法的高下分为:

好,不好和恶劣三种。

同时提供了一些解决这些问题的技巧。

首先解释一些java异常处理中必须搞清楚的定义和机制。Java语言规范将自Error类或RuntimeException类衍生出来的任何违例都称作“不可检查”(Unchecked)异常;其他所有异常则称作“可检查”(Checked)异常。

所谓可检查异常,是指我们应该自行处理的异常。至于处理的手段,要么加以控制(try catch),要么通告(throws)他们有可能产生。通常,应捕捉那些已知如何处理的异常,而通告那些不知如何处理的异常。

而对那些不可检查异常来说,他们要么在我们的控制之外(Error),要么是我们首先就不该允许的情况(RuntimeException)。

至于异常的指定,Java的规则非常简单:一个方法必须通告自己可能产生的所有可检查异常。编写自己的方法时,并不一定要通告出方法实际可能产生的每一个异常对象,要想理解什么时候必须要方法的throws丛句来通告异常,就必须知道对一个异常来说,他只有可能在下面四种情况下才会产生:

1.调用了可能产生异常的方法。比如BufferedReader类的readLine方法。该方法通告java.io.IOException异常

2。发现到一个错误,并用throw语句产生异常。

3.出现一个编程错误。比如a[-1] = 0。

4.Java产生内部错误。

如果出现头两种情况之一,必须告诉打算使用自己方法的人:假如使用这个方法,可能造成一个异常的产生(即在方法头上使用throws),一个简单的记忆方法:

只要含有throw,就要通告throws。如果一个方法必须同时处理多个异常,就必须在头内指出所有异常。

就像下例展示的那样,用逗号对他们进行分割:

1234567

    class Animation

    {

    public Image loadImage(Strint s)  throws EOFException,MalformedURLException

    {

    ……

    }

    }

然而,我们不需要通告内部java错误,也不应该通告自RuntimeException衍生出来的异常。

好的异常处理

好异常处理提供了处理程序错误的统一机制。事实上,Java语言通过向调用者提出异常警告的方式而显着地提升了软件开发中的异常处理能力。这种方式把Java语言中的“方法(method)”进行了扩展和增强,使之包括了自身的错误条件。下面就让我们看一个例子,这个例子说明了这种情况。

以下是FileInputStream构造器之一的原型:

public FileInputStream(String name) throws FileNotFoundException Java

的方法和构造器必须声明他们在被调用时可能“扔出”的异常,采用的关键字就是“throws”。这种在方法原型中出现的异常提示增加了编程的可靠性。

显而易见,这种方式是向方法的调用者提示了可能出现的异常条件,这样调用者就可以对这些异常作出适当的相应处理。以下代码示意我们是如何捕获并且处理FileNotFoundException 这一异常的:

 1234567891011

    try

    {

    FileInputStream fis = new FileInputStream(args[0]);

    // other code here …

    }

    catch (FileNotFoundException fnfe)

    {

    System.out.println("File: " + args[0] + " not found. Aborting.");

    System.exit(1);

    }

Java异常处理还有其他一些优秀的特性,这就是可检查异常、用户定义异常和在JDK 1.4中推出的新型Java记录API(Java Logging API)。java.lang.Exception的所有子类都属于可检查异常。可检查异常(checked exception)是扔出该异常的方法所必须提示的异常,这种异常必须被捕获或者向调用者提示。用户定义异常(User-defined exceptions)是定制的异常类,这种异常类扩展了java.lang.Exception类。优良的Java程序规定定制异常封装、报告和处理他们自己独有的情况。最新的Java记录API(logging API)则可以集中记录异常。 不好的Java异常处理

不好的一面包括两种情况:滥用不可检查异常(unchecked exceptions)和滥用catchall构造器等。这两种方式都使得问题变得复杂起来。

有一种类别的异常属于RuntimeException的子类,这种异常不会受到编译器的检查。比如,NullPointerException和 ArrayStoreException就是这种类型异常的实例。程序员可以对RuntimeException进行子类化以回避检查异常的限制,从而便于产生这些异常的方法为其调用者所使用。

专业的开发团队应当只允许在很少的情况下才可以这样做。

第二种异常处理的陋习是catchall构造器。所谓的“catchall 构造器”就是一种异常捕获代码模块,它可以处理所有扔给它的可能异常。

以下是catchall处理器的实例:

    123456789

    try

    {

    // code here with checked exceptions

    }

    catch (Throwable t)

    {

    t.printStackTrace();

    }

我得承认,我自己在编写一般程序的时候就曾经用过这种技术;但是,在编写关键程序的时候这种类型的构造器一定要避免使用,除非他们被授权可以和中央错误处理器联合使用才可以这样做。

除此之外,catchall构造器不过只是一种通过避免错误处理而加快编程进度的机制。

异常处理的一个不足之处是难以采用优良的错误处理策略。从低容内存状态恢复、写入错误和算法错误等异常情况都不是轻易能得到解决的。你可以尝试一下循环、垃圾收集和提醒用户等常用技术来应付以上的局面。

恶劣的处理方法

和许多Java特性及其API类似,Java的异常处理机制也有“霸王硬上弓”类的滑稽错误。比方说,为了扔出某个异常竟然毫不犹豫地用“new”关键词为其分配内存就是这样的例子。

我自己不知道有多少次就因为犯了这种错误而在严肃的编译器面前屡屡碰壁。在这种情况下,我们其实都是在伺候语言而不是让语言为我们所用。还有我们碰到的OutOfMemoryErrors就是异常处理的缺陷。这一处理过程是:

使用finally模块关闭文件,解析异常以得到出现问题的方法和代码行。在这一过程之内最大的缺陷是需要捕获OutOfMemoryError,而这一异常却并不是可检查异常!想想看,内存耗尽是相当常见的情况。任何与内存使用状态紧密相关的程序都应当捕获和处理这一错误。

使用异常时的一些建议

1.异常控制的设计宗旨并不是用来代替一些简单的测试。只有在异常情况下才使用异常!

2.不要过分细化异常。不要在每个语句上都加上异常处理,最好将整个任务都放在try块内。如果其中有一项操作失败,可以随即放弃任务。

3.不要“压制”异常。对于需要通告异常的方法,我们可以改用捕捉的方法来将异常强行关闭,如果真的出现异常,那个异常会被“静悄悄”的忽略。如果觉得产生的异常会非常重要,就必须多费些功夫,对其进行正确的控制。

4.不要介意异常的传递。如果调用的方法会产生异常,比如readLine方法,他们天生就能捕捉自己可能产生的异常,在这种情况下,一种更好地做法是将这些异常传递出去,而不是自己动手来捕捉它。

时间: 2024-11-03 22:22:56

Java 异常处理的优劣的相关文章

深入理解Java异常处理机制

1. 引子 try-catch-finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解.不过,我亲自体验的"教训"告诉我,这个东西可不是想象中的那么简单.听话.不信?那你看看下面的代码,"猜猜"它执行后的结果会是什么?不要往后看答案.也不许执行代码看真正答案哦.如果你的答案是正确,那么这篇文章你就不用浪费时间看啦. <span style="background-color: rgb(255, 255, 255

Java异常处理机制的秘密

一.结论 这些结论你可能从未听说过,但其正确性是毋庸置疑的,不妨先看看: 1.catch中throw不一定能抛回到上一层,因为finally中的return会抑制这个throw2.finally中throw一定能抛回上一层,因为此时其后的return不会被执行到(throw中断了正常的顺序流)3.在try/catch中return并不会直接返回上一层,而是先执行finally再返回 二.一段小程序 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

项目中java异常处理

一.java异常类介绍. Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类. 有一篇比较好的blog,http://blog.csdn.net/hguisu/article/details/6155636 介绍java异常. 二.异常处理方式. 在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常. 三.程序中使用. 2种处理方式 1.throw new 异常  在方法体上写throws

java异常处理和设计

在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常处理,当程序出错从哪里寻找出错的根源?但是如果一个项目异常处理设计地过多,又会严重影响到代码质量以及程序的性能.因此,如何高效简洁地设计异常处理是一门艺术,本文下面先讲述Java异常机制最基础的知识,然后给出在进行Java异常处理设计时的几个建议. 若有不正之处,请多多谅解和指正,不胜感激. 请尊重作者劳动成果,转载请标明

Java异常处理 “受控(checked)”的异常

示例程序: public class TestThrows { public static void main(String[] args) { FileInputStream fis = new FileInputStream("a.txt"); } } 为什么以上程序完全符合Java语法规范,但是却会报错呢? 修正: public class TestThrows { public static void main(String[] args) throws FileNotFoun

Java异常处理错误

Java异常处理错误 发现错误的最佳时期是在编译阶段,也就是在你运行程序之前.然而,编译期间并不能找出所有的错误,余下的问题必须在运行阶段解决.这就需要错误源通过某种方式把适当的信息传给某个接收者,该接收者知道如何处理这个问题. Java中的异常处理的目的在于通过使用少于目前数量的代码来简化大型,可靠的程序的生成,并且通过这种方式可以使你更加自信:你的应用中没有未处理的错误. 异常这个词有我对此感到意外的意思.问题出现了,你也许不清楚该如何处理,但你的确知道不该置之不理:你要停下来,看看是不是有

基础知识《十一》Java异常处理总结

Java异常处理总结 异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,你也许已经知道如何用if...else...来控制异常了,也许是自发的,然而这种控制异常痛苦,同一个异常或者错误如果多个地方出现,那么你每个地方都要做相同处理,感觉相当的麻烦! Java语言在设计的当初就考虑到这些问题,提出异常处理的框架的方案,所有的异常都可以用一个类型来表示,不同类型的异常对应不同的子类异常(这里的异常包括错误概念),定义异常处理的规范,在1.4版本以后增加了异常链机制,从而便于跟

Java 异常处理

异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常. 异常发生的原因有很多,通常包含以下几大类: 用户输入了非法数据. 要打开的文件不存在. 网络通信时连接中断,或者JVM内存溢出. 这些异常有的是因为用户错误引起,

java异常处理(父子异常的处理)

我当初学java异常处理的时候,对于父子异常的处理,我记得几句话“子类方法只能抛出父类方法所抛出的异常或者是其子异常,子类构造器必须要抛出父类构造器的异常或者其父异常”.那个时候还不知道子类方法为什么要这样子抛出异常,后来通过学习<Thinking in Java>,我才明白其中的道理,现在我再来温习一下. 一.子类方法只能抛出父类方法的异常或者是其子异常 对于这种限制,主要是因为子类在做向上转型的时候,不能正确地捕获异常 package thinkinginjava; public abst