`

11条Java异常处理的最佳实践

阅读更多

在之前关于Java异常的文章中,已经探讨过suppressed exceptionsJava 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的时候,一般都是不可恢复的情况。

为异常记录合适的文档

为应用中定义的异常定义合适的文档,如果你写了一个自定义的异常却没有文档,其他开发者会不清楚这个异常的含义,为你定义的异常配备对应的文档是一个非常好的习惯。

 

转载:【译】11条Java异常处理的最佳实践 
参考:Java异常处理的10个最佳实践

  • 大小: 434.2 KB
0
2
分享到:
评论

相关推荐

    Java 异常处理的 9 个最佳实践

    Java 异常处理的 9 个最佳实践,在处理异常时可以参考。

    Java异常处理和最佳实践(含案例分析).pdf

    Java异常处理和最佳实践(含案例分析)

    Java异常处理的最佳实践

    Java异常,大家都很熟悉。那么具体操作是怎么样的呢?下面从基础开始,带大家一块了解是怎么实践的。本文是关于Exception处理的一篇不错的文章,从Java Exception的概念介绍起,依次讲解了Exception的类型(Checked/...

    Java 异常处理面试集锦及答案20道

    异常处理是Java编程中重要的概念和技巧之一,也是面试中常见的考点。...通过阅读本文,您将能够深入了解Java异常处理的原理、使用方法以及异常处理的最佳实践。不论您是准备面试还是希望加强对Java异常处理的知识掌握

    Java异常处理.md

    Java异常处理是编写健壮程序的关键方面之一。本资料将帮助您了解异常类层次结构、异常处理、抛出异常、自定义异常和最佳实践。 在Java中,异常被分为受检异常和非受检异常。受检异常需要在编译时进行处理,而非受检...

    详解Java异常处理最佳实践及陷阱防范

    主要介绍了Java异常处理最佳实践及陷阱防范,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Java编程异常处理最佳实践【推荐】

    主要介绍了Java编程异常处理最佳实践【推荐】,具有一定参考价值,需要的朋友可以了解下。

    EventBus最佳实践:Java手撕实现ESB底层事件委托处理机制的思路,配套演示代码

    本代码实现了一个简单的EventBus结构。 当一个组织中的人数众多,我们需要将关注点拆分,以避免陷入逻辑混乱和不必要的代码冲突,而且能带来一些可以让组件复用的好处。 但是如果将一个复杂的问题解耦成若干个小问题...

    Java编程中10个最佳的异常处理技巧

    主要介绍了Java编程中10个最佳的异常处理技巧,在本文中,将讨论Java异常处理最佳实践,这些Java最佳实践遵循标准的JDK库,和几个处理错误和异常的开源代码,这还是一个提供给java程序员编写健壮代码的便利手册,需要的...

    java8集合源码分析-noah-bestPractices:Java业务最佳实践与踩坑

    Noah-Java最佳实践与踩坑 查看详细文章,可以参考我的博客 代码篇 01 使用了并发工具类库,线程安全就高枕无忧了吗?: 02 代码加锁:不要让“锁”事成为烦心事: 03 线程池:业务代码最常用也最容易犯错的组件: 04...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    前 言 致 谢 第一部分 走近Java 第1章 走近Java / 2 1.1 概述 / 2 1.2 Java技术体系 / 3 1.3 Java发展史 / 5 1.4 展望Java技术的未来 / 9 1.4.1 模块化 / 9 1.4.2 混合语言 / 9 1.4.3 多核并行 / 11 ...

    java-best-practices:编码,设计和架构Java应用程序的最佳实践

    从最畅销的5门课程中学习在28分钟的惊人学习路径中进行重新训练Java最佳实践Java最佳实践程序员之旅如何成为一名优秀的程序员? 问为什么? 编程常见问题我应该成为所有设计模式的专家吗? 什么是NFR? 编码Java技巧...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    《深入Java虚拟机(原书第2版)》,原书名《Inside the Java Virtual Machine,Second Edition》,作者:【美】Bill Venners,翻译:曹晓钢、蒋靖,出版社:机械工业出版社,ISBN:7111128052,出版日期:2003 年 9 ...

    NodeJS错误处理最佳实践1

    背景本文假设:你已经熟悉了JavaScript、Java、 Python、 C++ 或者类似的语言中异常的概念,而且你知道抛出异常和捕获异常是什么意思。你熟悉怎

    【Java面试+Java学习指南】 一份涵盖大部分Java程序员所需要掌握的核心知识

    Java异常 解读Java中的回调 反射 泛型 枚举类 Java注解和最佳实践 JavaIO流 多线程 深入理解内部类 javac和javap Java8新特性终极指南 序列化和反序列化 继承、封装、多态的实现原理 容器 Java集合类总结 Java集合...

    廖雪峰 Java 教程.doc

    廖雪峰 Java 教程 Java教程 Java快速入门 Java简介 安装JDK 第一个Java程序 ...Java代码助手 ...Java程序基础 ...最佳实践 单元测试 编写JUnit测试 使用Fixture 异常测试 条件测试 参数化测试

    数据结构算法Java实现。关于Java《数据结构算法》核心技术学习积累的例子,是初学者及核心技术巩固的最佳实践。.zip

    安全:Java提供了丰富的安全特性,如禁止指针运算、自动内存管理和异常处理机制,以减少程序错误和恶意攻击的可能性。 可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动...

    Java工程师面试复习指南

    Java异常 解读Java中的回调 反射 泛型 枚举类 Java注解和最佳实践 JavaIO流 多线程 深入理解内部类 javac和javap Java8新特性终极指南 序列化和反序列化 继承封装多态的实现原理 集合类 Java集合类总结 Java集合详解...

    Java岗位常规面试题.pdf

    请说明在Java中异常处理的方法和最佳实践。 6. Java中的什么机制实现了自动内存管理(Automatic Memory Management)?请描述这种机制的工作原理。 7. 什么是Java中的单例模式(Singleton Pattern)?请说明如何实现...

    java面试手册及各类java书籍

    性能优化篇:分析Java应用的性能瓶颈,提供优化策略和最佳实践,帮助读者提升应用的性能。 面试题解析篇:精选大量Java面试题,并给出详细的解析和答案,帮助读者更好地应对面试挑战。 特色亮点: 权威性与实用性:...

Global site tag (gtag.js) - Google Analytics