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 步骤,他们天生就能 捉拿自己可能产生的 异样,在这种状况下,一种更好地做法是将这些 异样传递出去,而不是自己 着手来 捉拿它 。 |