在之前关于Java异常的文章中,已经探讨过suppressed exceptions和Java Exceptions Tutorial 两个方面的内容。要想在实际项目中正确处理Java异常,你应该熟练掌握一些Java异常处理的最佳实践。
不要 在catch语句块中压制异常
public class ExceptionExample { public FileInputStream testMethod1(){ File file = new File("test.txt"); FileInputStream fileInputStream = null; try{ fileInputStream = new FileInputStream(file); fileInputStream.read(); }catch (IOException e){ return null; } return fileInputStream; } public static void main(String[] args){ ExceptionExample instance1 = new ExceptionExample(); instance1.testMethod1(); } }
在异常处理时进行异常压制是非常不好的编程习惯,上面的例子中,无论抛出什么异常都会被忽略,以至没有留下任何问题线索。如果在这一层次不知道如何处理异常,最好将异常重新抛出,由上层决定如何处理异常。
public class ExceptionExample { public FileInputStream testMethod1() throws IOException{ File file = new File("test.txt"); FileInputStream fileInputStream = null; try{ fileInputStream = new FileInputStream(file); fileInputStream.read(); }catch (IOException e){ throw e; } return fileInputStream; } public static void main(String[] args) throws IOException{ ExceptionExample instance1 = new ExceptionExample(); instance1.testMethod1(); } }
要在方法定义分句中定义具体的异常
按照public FileInputStream testMethod1() throws Exception{这种写法,表示该方法会抛出所有受检查异常,这不是一个良好的编程习惯。在这种情况下,我们最好抛出足够具体的异常,以便调用者进行合适的捕获和处理,例如public FileInputStream testMethod1() throws IOException{。
捕获具体的异常
在调用其他模块时,最好捕获由该模块抛出的具体的异常。如果某个被调用模块抛出了多个异常,那么只捕获这些异常的父类是不好的编程习惯。
例如,如果一个模块抛出FileNotFoundException和IOException,那么调用这个模块的代码最好写两个catch语句块分别捕获这两个异常,而不要只写一个捕获Exception的catch语句块。
正确的写法如下:
try { //some statements catch(FileNotFoundException e){ //handle here } catch(IOException e){ //handle here }
你最好不要这么写:
try { //some statements catch(Exception e){ //handle here }
记得在finally语句块中释放资源
当你在代码中建立了数据库连接、文件操作符或者其他需要被及时释放的系统资源,如果你没有及时释放这些资源,会影响到系统的性能。
为了避免这种情况发生,可以使用Java 7的try(open the resources) {deal with resources}语句,如果你还是习惯这种老式写法,则可以按照如下方式写:
finally { try { if (con != null) { con.close(); } if (stat != null) { stat.close(); } } catch (SQLException sqlee) { sqlee.printStackTrace(); } }
异常会影响性能
异常处理的性能成本非常高,每个Java程序员在开发时都应牢记这句话。创建一个异常非常慢,抛出一个异常又会消耗1~5ms,当一个异常在应用的多个层级之间传递时,会拖累整个应用的性能。
仅在异常情况下使用异常;
在可恢复的异常情况下使用异常;
尽管使用异常有利于Java开发,但是在应用中最好不要捕获太多的调用栈,因为在很多情况下都不需要打印调用栈就知道哪里出错了。因此,异常消息应该提供恰到好处的信息。
避免在finally语句块中抛出异常
try { method(); //here throws first exception } finally { shutdown(); //If finally blockthrew any exception the first exception will be lost forever }
在上面的这个代码片段中,finally代码块也可能再次抛出异常。如果同时抛出两个异常,则第一个异常的调用栈会丢失。在finally语句块中最好只做打印错误信息或者关闭资源等操作,避免在finally语句块中再次抛出异常。
finally中避免有return 语句,否则之前抛出的异常不会被捕获.
使用标准异常
如果使用内建的异常可以解决问题,就不要定义自己的异常。Java API提供了上百种针对不同情况的异常类型,在开发中首先尽可能使用Java API提供的异常,如果标准的异常不能满足你的要求,这时候创建自己的定制异常。尽可能得使用标准异常有利于新加入的开发者看懂项目代码。
正确得包装异常类型
当需要在应用重新抛出异常时,应该正确得包装原始异常,否则会丢失原始异常,例如下面的例子中:
import java.io.IOException; public class HelloWorld{ public static void main(String []args) throws Exception{ try{ throw new IOException("IOException"); }catch (IOException e){ throw new ExampleException1("Example Exception and " + e.getMessage()); } } } class ExampleException1 extends Exception{ public ExampleException1(String s, Throwable t){ super(s,t); } public ExampleException1(String s){ super(s); } }
这个程序的输出为:
Exception in thread "main" ExampleException1: Example Exception and IOException at HelloWorld.main(HelloWorld.java:8)
这里发现,IOException的调用栈已经丢失了,因为我们在catch语句块中没有正确包装IOException。若将catch语句块修改成下面这样,这可以发现原始异常的调用栈也被打印出来了。
catch (IOException e){ throw new ExampleException1("Example Exception",e); }
这时候的输出如下:
Exception in thread "main" ExampleException1: Example Exception at HelloWorld.main(HelloWorld.java:8) Caused by: java.io.IOException: IOException at HelloWorld.main(HelloWorld.java:6)
不要使用异常控制程序的流程
不应该使用异常控制应用的执行流程,例如,本应该使用if语句进行条件判断的情况下,你却使用异常处理,这是非常不好的习惯,会严重影响应用的性能。
不要捕获Throwable类
在应用中不应捕获Throwable类,Error是Throwable类的子类,当应用抛出Errors的时候,一般都是不可恢复的情况。
为异常记录合适的文档
为应用中定义的异常定义合适的文档,如果你写了一个自定义的异常却没有文档,其他开发者会不清楚这个异常的含义,为你定义的异常配备对应的文档是一个非常好的习惯。
相关推荐
Java异常处理的9个最佳实践涵盖了开发者在进行Java编程时应当遵循的一系列规则和方法,以确保代码的健壮性和可维护性。异常处理是编程中的一个重要部分,它能够帮助我们更有效地管理和响应程序运行时的错误情况。 ...
Java编程异常处理最佳实践【推荐】 Java中的异常处理是非常重要的,特别是在大型项目中,异常处理机制的设计和实现将直接影响系统的稳定性和可靠性。 Java中的异常处理机制可以分为两大类:Checked Exception和...
"Java异常处理和最佳实践(含案例分析)" 本文将深入探讨Java中的异常处理机制,讨论如何正确地处理Java异常,避免常见的错误和best practice。通过本文的学习,您将了解Java异常的分类、为什么finally块中的代码...
本文主要探讨了Java异常处理的最佳实践,包括理解异常的类型、何时何地使用异常,以及如何有效地处理它们。 首先,Java异常分为两种主要类型:Checked异常和Unchecked异常。Checked异常,如IOException和...
这篇博文链接(已提供但无法直接访问)可能详细解释了Java异常处理的基本概念、机制以及最佳实践。 Java异常处理的核心在于五个关键字:try、catch、finally、throw和throws。这些关键字帮助程序员构建了一个框架,...
Java异常处理设计是Java编程中一个至关重要的环节,它直接影响到程序的稳定性和可维护性。在Java中,异常处理是通过try-catch-finally语句块来实现的,主要涉及两大类异常:编译时异常(Checked Exception)和运行时...
### Java异常处理总结 #### 一、Java异常的基础知识 在Java编程中,异常处理是一项极其重要的技术。异常处理能够帮助开发者优雅地处理程序运行时遇到的问题,避免程序崩溃,并提供给用户友好的反馈信息。 **什么...
通过遵循上述最佳实践,开发者可以编写出更健壮、可维护的Java代码,有效地利用Java异常处理机制来提高程序的稳定性。同时,阅读并理解"Effective Java Exceptions"文档可以帮助进一步深化对Java异常处理的理解。
7. **异常处理的最佳实践**: - 尽量避免在`catch`块中只打印堆栈跟踪,而应提供有用的错误信息或采取适当的恢复措施。 - 使用多个`catch`块来分别处理不同类型的异常,以便更精确地处理问题。 - 不要忽略异常,...
Java的异常处理机制为程序的错误处理提供了一种结构化和可预测的方法。通过合理使用try、catch、finally、throw和throws关键字,开发者可以编写出更加健壮和易于维护的代码。掌握异常处理的最佳实践,可以帮助我们更...
六、异常处理最佳实践 1. 尽量避免在finally块中进行复杂的操作,因为这可能导致新的异常。 2. 不要忽视异常,即使异常看起来不严重,也应适当地处理或记录。 3. 使用具体异常类型,而不是过于宽泛的Exception类,...
Java的异常处理是编程中一个重要的概念,它用于在程序运行过程中捕获并处理错误情况。异常处理的主要目的是保持程序的稳定性和优雅性,避免因为未预期的问题导致程序崩溃。在Java中,异常处理通过使用try-catch块来...
Java异常处理是编程中至关重要的一个部分,它用于管理和恢复程序执行过程中可能出现的错误或异常情况。当程序遇到无法预见的问题,如文件未找到、网络连接中断或计算溢出等,Java通过异常处理机制来优雅地处理这些...
Java异常处理是编程中至关重要的一个环节,它帮助开发者在程序运行时捕获并处理错误,确保程序的健壮性和稳定性。在这个Java异常处理教程中,我们将深入探讨这个主题,以便提升你的Java编程技能。 首先,Java异常是...
本教程将深入探讨Java异常处理的基础、原则以及最佳实践。 一、异常的分类 Java中的异常类层次结构主要基于`java.lang.Throwable`类,它有两个主要子类:`Error`和`Exception`。`Error`通常表示系统级的错误,如...
下面我们将深入探讨如何处理Java异常,并遵循一些最佳实践。 首先,我们来看一个常见的问题——在`finally`块中清理资源。在处理可能会抛出异常的IO操作时,我们需要确保资源在使用完毕后被正确关闭。通常,我们会...
《Java Enterprise 最佳实践》是Java开发者们深入理解企业级应用开发的重要参考资料,尤其是其中的JDBC最佳实践部分,对于数据库交互的优化和性能提升有着关键性的影响。JDBC(Java Database Connectivity)是Java...
Java编码最佳实践是提高代码质量、可读性、性能和可维护性的关键。这份指南涵盖了多个方面的编程建议,旨在帮助开发者遵循良好的编程习惯,确保代码的高效运行。 1. **资源管理**:在处理文件、流或其他资源时,...