在之前关于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异常,大家都很熟悉。那么具体操作是怎么样的呢?下面从基础开始,带大家一块了解是怎么实践的。本文是关于Exception处理的一篇不错的文章,从Java Exception的概念介绍起,依次讲解了Exception的类型(Checked/...
异常处理是Java编程中重要的概念和技巧之一,也是面试中常见的考点。...通过阅读本文,您将能够深入了解Java异常处理的原理、使用方法以及异常处理的最佳实践。不论您是准备面试还是希望加强对Java异常处理的知识掌握
Java异常处理是编写健壮程序的关键方面之一。本资料将帮助您了解异常类层次结构、异常处理、抛出异常、自定义异常和最佳实践。 在Java中,异常被分为受检异常和非受检异常。受检异常需要在编译时进行处理,而非受检...
主要介绍了Java异常处理最佳实践及陷阱防范,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
主要介绍了Java编程异常处理最佳实践【推荐】,具有一定参考价值,需要的朋友可以了解下。
本代码实现了一个简单的EventBus结构。 当一个组织中的人数众多,我们需要将关注点拆分,以避免陷入逻辑混乱和不必要的代码冲突,而且能带来一些可以让组件复用的好处。 但是如果将一个复杂的问题解耦成若干个小问题...
主要介绍了Java编程中10个最佳的异常处理技巧,在本文中,将讨论Java异常处理最佳实践,这些Java最佳实践遵循标准的JDK库,和几个处理错误和异常的开源代码,这还是一个提供给java程序员编写健壮代码的便利手册,需要的...
Noah-Java最佳实践与踩坑 查看详细文章,可以参考我的博客 代码篇 01 使用了并发工具类库,线程安全就高枕无忧了吗?: 02 代码加锁:不要让“锁”事成为烦心事: 03 线程池:业务代码最常用也最容易犯错的组件: 04...
前 言 致 谢 第一部分 走近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 ...
从最畅销的5门课程中学习在28分钟的惊人学习路径中进行重新训练Java最佳实践Java最佳实践程序员之旅如何成为一名优秀的程序员? 问为什么? 编程常见问题我应该成为所有设计模式的专家吗? 什么是NFR? 编码Java技巧...
《深入Java虚拟机(原书第2版)》,原书名《Inside the Java Virtual Machine,Second Edition》,作者:【美】Bill Venners,翻译:曹晓钢、蒋靖,出版社:机械工业出版社,ISBN:7111128052,出版日期:2003 年 9 ...
背景本文假设:你已经熟悉了JavaScript、Java、 Python、 C++ 或者类似的语言中异常的概念,而且你知道抛出异常和捕获异常是什么意思。你熟悉怎
Java异常 解读Java中的回调 反射 泛型 枚举类 Java注解和最佳实践 JavaIO流 多线程 深入理解内部类 javac和javap Java8新特性终极指南 序列化和反序列化 继承、封装、多态的实现原理 容器 Java集合类总结 Java集合...
廖雪峰 Java 教程 Java教程 Java快速入门 Java简介 安装JDK 第一个Java程序 ...Java代码助手 ...Java程序基础 ...最佳实践 单元测试 编写JUnit测试 使用Fixture 异常测试 条件测试 参数化测试
安全:Java提供了丰富的安全特性,如禁止指针运算、自动内存管理和异常处理机制,以减少程序错误和恶意攻击的可能性。 可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动...
Java异常 解读Java中的回调 反射 泛型 枚举类 Java注解和最佳实践 JavaIO流 多线程 深入理解内部类 javac和javap Java8新特性终极指南 序列化和反序列化 继承封装多态的实现原理 集合类 Java集合类总结 Java集合详解...
请说明在Java中异常处理的方法和最佳实践。 6. Java中的什么机制实现了自动内存管理(Automatic Memory Management)?请描述这种机制的工作原理。 7. 什么是Java中的单例模式(Singleton Pattern)?请说明如何实现...
性能优化篇:分析Java应用的性能瓶颈,提供优化策略和最佳实践,帮助读者提升应用的性能。 面试题解析篇:精选大量Java面试题,并给出详细的解析和答案,帮助读者更好地应对面试挑战。 特色亮点: 权威性与实用性:...