`
sungang_1120
  • 浏览: 325098 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类

Effective Java学习(异常)之——只针对异常的情况才使用异常

阅读更多

充分发挥异常的优点,可以提高程序的可读性、可靠性和可维护性。如果使用不当,它们也会带来负面影响。

 

某一天,如果你不走运的话,可能会碰到下面这样的代码:

try {
	int i = 0;
	while(true){
		range[i++].climb();
			}
	} catch (ArrayIndexOutOfBoundsException e) {
			
}

       这段代码有什么作用?看起来根本不明显他没有真正被使用的原因是没有更好的进行优化。事实证明,作为一个要对数组元素进行遍历的实现方式,他的构思是非常拙劣的。当这个循环企图访问数组边界之外的第一个数组元素时,用抛出,捕获、忽略ArrayIndexOutOfBoundsException的手段来达到终止无限循环的目的。假定他与数组循环的标准模式是等价的,对于任何一个Java程序员来说,下面的标准模式一看就会明白:

for(Mountain m : range){
     m.climb();
}

    那么,为什么有人会优先使用基于异常的模式,而不是用行之有效的模式呢?这是被误导了,他们企图利用Java的错误判断机制来提高性能,因为VM对每次数组访问都要检查越界情况,所以他们认为正常的循环终止测试被编译器隐藏了,但是在for-each循环中仍然可见,这无疑是多余的,应该避免。这种想法有三个错误:

 

一,因为异常机制的设计初衷使用于不正常的情形,所以很少会有JVM实现试图对它们进行优化,使得与显式的测试一样快速。

 

二,把代码放在try-cathch块中反而阻止了现代JVM实现本来可能要执行的某些特定优化。

 

三,对数组进行遍历的标准模式并不会导致冗余的检查,有些现代的JVM实现会将它们优化掉。

 

实际上,在现代的JVM实现上,基于异常的模式比标准模式要慢得多。

 

    基于异常的循环不仅模糊了代码的意图,降低了他的性能,而且他还不能保证正常的工作,如果出现了不相关的bug,这个模式会悄悄的失效,从掩盖了这个bug,极大的增加了调试过程的复杂性。假设循环体中的计算过程调用了一个方法,这个方法执行了对某个不相关数组的越界访问。如果使用合理的模式,这个bug会产生未被捕捉的异常,从而导致线程立即结束,产生完整的堆栈轨迹。如果使用这个误导的基于异常的循环模式,与这个BUG相关的异常将会被扑捉到,并且被错误的解释为正常的循环终止条件。

 

    这个例子的教训很简单:顾名思义,异常应该只用于异常的情况下,他们永远不应该用于正常的控制流。更一般的,应该优先使用标准的。容易理解的模式,而不是那么声称可以提供更好性能的、弄巧成拙的办法。即使真的能够改进性能,面对平台实现的不断改进,这么模式的性能优势也不可能一直保持。然而,由这种过度聪明的模式带来的微妙的bug,以及维护的痛苦却依然存在。

 

    这条原则对于API设计也有启发,设计良好的API不应该被强迫他的客户端为了正常的控制流而使用异常。如果类具有“状态相关”的方法,即只有在特定的不可预知的条件下才可以被调用的方法,这个类往往也应该有个单独的“状态测试”方法,即指示是否可以调用这个状态相关的方法。例如,Iterable接口有一个状态相关的next方法,和相应的状态测试方法hasNext方法。这使得利用传统for循环对集合进行迭代的标准模式成为可能:

for(Iterator<Foo> i = collection.iterator(); i.hasNext();){
      Foo foo = i.next();
}

 如果Iterator缺少hasNext方法,客户端将被迫该用下面的做法:

try{
      Iterator<Foo> i = collection.iterator();
      while(i.hasNext()){
              Foo foo = i.next();
      }
}catch(NoSuchElementException e){
     
}

     这应该非常类似与开始那个例子。除了代码繁琐且令人误解之外,这个基于异常的模式可能执行起来也比标准模式更差,并且还可能掩盖系统中其他不相关部分中bug。

 

    另一种提供单独的状态测试方法的做法是,如果“状态相关的”方法被调用时,该对象处于不适当的状态之中,他就会返回一个可识别的值,比如null。这种方法对于Iterator而言并不适合,因为null是next方法的合法返回值。

 

     对于“状态测试方法”和“可识别的返回值”这两种做法,有些知道原则可以帮助你在两者之中做出选择。如果对象将在缺少外部同步的情况下被并发访问,或者可被外界改变状态,使用可被识别的返回值可能很有必要的,因为在调用“状态测试”方法必须重复“状态相关”方法的工作,从性能的角度考虑,就应该使用可识别的返回值。如果其他所有方面都等同的,那么“状态测试”方法则略优于可被识别的返回值。他提供了更好的可读性,对于使用不当的情形,可能更加易于检测和改正:如果忘了去调用状态测试方法,状态相关的方法就会抛出异常,使这个bug变的很明显;如果忘了去检查可识别的返回值,这个bug就很难被发现。

 

    总而言之,异常是为了在异常情况下使用而设计的,不要将他们用于普通的控制流,也不要编写迫使他们这么做的API。 

 

分享到:
评论

相关推荐

    Effective Java读书笔记.pdf

    Effective Java是一本关于Java编程语言的经典书籍,本笔记主要总结了Java语言的发展历程、静态工厂方法的应用、构造器模式的使用等重要知识点。 一、Java语言的发展历程 Java语言的发展可追溯到1991年,当时由...

    Effective Java第三版1

    《Effective Java》是Java编程领域的一本经典著作,由Joshua Bloch撰写,该书的第三版继续提供了关于如何编写高效、优雅、可维护的Java代码的指导。以下是基于给出的目录和部分内容提取的一些关键知识点: ### 第一...

    Effective java 3 学习记录.docx

    Effective Java 3 学习记录 本学习记录主要介绍了 Effective Java 3 中的静态工厂方法和 Builder 模式两部分内容。 一、静态工厂方法 静态工厂方法是指返回类实例的命名规则,例如:from、of、valueOf、instance ...

    java设计模式之——策略模式

    在阅读《Effective Java》等编程书籍时,会发现作者常常推荐使用策略模式来代替使用重载方法或枚举类型,因为这提供了更好的灵活性和可扩展性。 总结一下,策略模式是设计模式中的重要一环,它通过将算法封装在独立...

    effective-java.pdf

    标题“effective-java.pdf”与描述“effective-java.pdf”表明本文档是关于Java编程实践的指南,且内容可能来自于一本名为《Effective Java》的书籍,该书是由Joshua Bloch编写,被广泛认为是Java编程的权威指南。...

    effective java 读书笔记

    《Effective Java》是Java开发领域的经典著作,作者Joshua Bloch深入浅出地阐述了编写高效、健壮的Java代码的技巧和最佳实践。以下是对该书部分内容的详细解释: 1. **产生和销毁对象** - Item1:静态工厂方法相比...

    Effective.Enterprise.Java.中文版 高清pdf 下载

    《Effective Enterprise Java》是Java开发领域的一本经典著作,由著名技术专家Bill Venners编著,被广大Java开发者誉为“四大名著”之一。这本书深入探讨了在企业级Java开发中如何写出高效、可维护和易于理解的代码...

    高效java异常处理机制

    尽量保持每个catch块的针对性,只捕获预期的特定异常。 4. **优先使用标准异常** 尽可能使用Java标准库提供的异常类,如IllegalArgumentException、NullPointerException等,这有助于提供一致的错误处理体验,并...

    effectiveJava课件分享

    在编程领域,特别是Java开发中,"Effective Java"是一本非常经典的书籍,由Joshua Bloch撰写,书中提出了一系列最佳实践和设计原则,以帮助开发者编写出更高效、更安全的代码。根据提供的标题和描述,我们将探讨三个...

    sixteenbells#effective-java-3rd-chinese#69. 只针对异常的情况下才使用异常1

    如果类中具有「状态相关」(state-dependent)的方法,即只有在特定的不可预知的条件下才可以被调用的方法,这个类往往也应该具有一个单独的「状态测试」

    effective-java 配套代码

    《Effective Java》是Java开发领域的一本经典著作,由Joshua Bloch撰写,书中提出了一系列编程最佳实践和设计模式,帮助开发者写出更高效、更可靠、更易于维护的Java代码。配套代码`effective-java-examples-master`...

    《Effective Java》读书分享.pptx

    "Effective Java 读书分享" 《Effective Java》读书分享.pptx 是一本 Java 编程语言指南,旨在帮助开发者编写高质量、可维护的 Java 代码。该书包含 90 个条目,每个条目讨论一条规则,涵盖了 Java 编程语言的...

    effective enterprise java 中文版

    《Effective Enterprise Java》是一本由James Gosling、Bill Venners和Cay S. Horstmann合著的经典著作,旨在帮助Java开发者深入理解和利用企业级Java技术。这本书提供了78条具体的建议,涵盖了从设计模式到并发编程...

    Effective Enterprise Java(中文) Effective Enterprise Java(中文)

    本书详细介绍企业级计算技术中的常见问题,并描述使用企业级Java平台技术处理这些问题的方法。本书以若干条建议、揸南的形式,言简意赅地介绍了J2EE开发中的微妙之处。无论你是否是Java开发人员,本书都将为你开发...

    Effective Enterprise Java

    通过学习《Effective Enterprise Java》,开发者不仅能掌握Java EE的关键技术和工具,还能理解如何在实际项目中运用这些知识,以解决企业级软件开发中的挑战。这本书是Java EE开发者必备的参考资料,无论你是初学者...

    Effective Java.docx

    ### Effective Java - 创建和销毁对象 #### 第一条:用静态工厂方法代替构造器 **优点:** 1. **命名清晰,易于使用:** 静态工厂方法通过明确的命名方式,使得用户更容易理解方法的功能及其预期结果。例如,`...

    Effective Java.zip

    《Effective Java》是一本经典Java编程指南,作者是Joshua Bloch,这本书深入探讨了...以上内容仅是《Effective Java》各章节的部分知识点概述,书中还有更多关于Java编程的最佳实践和深入理解等待读者去发掘和学习。

    Effective-Java-2nd-Edition-(May-2008).zip_effective java

    11. **异常处理**:讨论了异常的使用和滥用,提倡正确使用checked异常和unchecked异常,以及何时使用异常链和自定义异常。 12. **并发编程**:书中简要介绍了一些并发编程的最佳实践,如使用并发工具类(如...

Global site tag (gtag.js) - Google Analytics