List

  1. Never swallow the exception in catch block
  2. Declare the specific checked exceptions that your method can throw
  3. Do not catch the Exception class rather catch specific sub classes
  4. Never catch Throwable class
  5. Always correctly wrap the exceptions in custom exceptions so that stack trace is not lost
  6. Either log the exception or throw it but never do the both
  7. Never throw any exception from finally block
  8. Always catch only those exceptions that you can actually handle
  9. Don't use printStackTrace() statement or similar methods
  10. Use finally blocks instead of catch blocks if you are not going to handle exception
  11. Remember "Throw early catch late" principle
  12. Always clean up after handling the exception
  13. Throw only relevant exception from a method
  14. Never use exceptions for flow control in your program
  15. Validate user input to catch adverse conditions very early in request processing
  16. Always include all information about an exception in single log message
  17. Pass all relevant information to exceptions to make them informative as much as possible
  18. Always terminate the thread which it is interrupted
  19. Use template methods for repeated try-catch
  20. Document all exceptions in your application in javadoc

Before we dive into deep concepts of exception handling best practices, lets start with one of the most important concepts which is to understand that there are three general types of throwable classes in Java: checked exceptions, unchecked exceptions, and errors.

Type of exceptions

Checked exceptions are exceptions that must be declared in the throws clause of a method. They extend Exception and are intended to be an “in your face” type of exceptions. Java wants you to handle them because they somehow are dependent on external factors outside your program. A checked exception indicates an expected problem that can occur during normal system operation. Mostly these exception happen when you try to use external systems over network or in file system. Mostly, the correct response to a checked exception should be to try again later, or to prompt the user to modify his input.

Unchecked exceptions are exceptions that do not need to be declared in a throws clause. JVM simply doesn’t force you to handle them as they are mostly generated at runtime due to programmatic errors. They extend RuntimeException. The most common example is a NullPointerException [Quite scary.. Isn’t it?]. An unchecked exception probably shouldn’t be retried, and the correct action should be usually to do nothing, and let it come out of your method and through the execution stack. At a high level of execution, this type of exceptions should be logged.

Errors are serious runtime environment problems that are almost certainly not recoverable. Some examples are OutOfMemoryError, LinkageError, and StackOverflowError. They generally crash you program or part of program. Only a good logging practice will help you in determining the exact causes of errors.

User defined custom exceptions

Anytime when user feels that he wants to use its own application specific exception for some reasons, he can create a new class extending appropriate super class (mostly its Exception.java) and start using it in appropriate places. These user defined exceptions can be used in two ways:

1) Either directly throw the custom exception when something goes wrong in application

throw new DaoObjectNotFoundException("Couldn't find dao with id " + id);

2) Or wrap the original exception inside custom exception and throw it

catch (NoSuchMethodException e) {
throw new DaoObjectNotFoundException("Couldn't find dao with id " + id, e);
}

Wrapping an exception can provide extra information to the user by adding your own message/ context information, while still preserving the stack trace and message of the original exception. It also allows you to hide the implementation details of your code, which is the most important reason to wrap exceptions.

Now lets start exploring the best practices followed for exception handling industry wise.

Best practices you must consider and follow

1) Never swallow the exception in catch block

catch (NoSuchMethodException e) {
return null;
}

Doing this not only return “null” instead of handling or re-throwing the exception, it totally swallows the exception, losing the cause of error forever. And when you don’t know the reason of failure, how you would prevent it in future? Never do this !!

2) Declare the specific checked exceptions that your method can throw

public void foo() throws Exception { //Incorrect way
}

Always avoid doing this as in above code sample. It simply defeats the whole purpose of having checked exception. Declare the specific checked exceptions that your method can throw. If there are just too many such checked exceptions, you should probably wrap them in your own exception and add information to in exception message. You can also consider code refactoring also if possible.

public void foo() throws SpecificException1, SpecificException2 { //Correct way
}

3) Do not catch the Exception class rather catch specific sub classes

try {
someMethod();
} catch (Exception e) {
LOGGER.error("method has failed", e);
}

The problem with catching Exception is that if the method you are calling later adds a new checked exception to its method signature, the developer’s intent is that you should handle the specific new exception. If your code just catches Exception (or Throwable), you’ll never know about the change and the fact that your code is now wrong and might break at any point of time in runtime.

4) Never catch Throwable class

Well, its one step more serious trouble. Because java errors are also subclasses of the Throwable. Errors are irreversible conditions that can not be handled by JVM itself. And for some JVM implementations, JVM might not actually even invoke your catch clause on an Error.

5) Always correctly wrap the exceptions in custom exceptions so that stack trace is not lost

catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " + e.getMessage()); //Incorrect way
}

This destroys the stack trace of the original exception, and is always wrong. The correct way of doing this is:

catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " , e); //Correct way
}

6) Either log the exception or throw it but never do the both

catch (NoSuchMethodException e) {
LOGGER.error("Some information", e);
throw e;
}

As in above example code, logging and throwing will result in multiple log messages in log files, for a single problem in the code, and makes life hell for the engineer who is trying to dig through the logs.

7) Never throw any exception from finally block

try {
someMethod(); //Throws exceptionOne
} finally {
cleanUp(); //If finally also threw any exception the exceptionOne will be lost forever
}

This is fine, as long as cleanUp() can never throw any exception. In the above example, if someMethod() throws an exception, and in the finally block also, cleanUp() throws an exception, that second exception will come out of method and the original first exception (correct reason) will be lost forever. If the code that you call in a finally block can possibly throw an exception, make sure that you either handle it, or log it. Never let it come out of the finally block.

8) Always catch only those exceptions that you can actually handle

catch (NoSuchMethodException e) {
throw e; //Avoid this as it doesn't help anything
}

Well this is most important concept. Don’t catch any exception just for the sake of catching it. Catch any exception only if you want to handle it or, you want to provide additional contextual information in that exception. If you can’t handle it in catch block, then best advice is just don’t catch it only to re-throw it.

9) Don’t use printStackTrace() statement or similar methods

Never leave printStackTrace() after finishing your code. Chances are one of your fellow colleague will get one of those stack traces eventually, and have exactly zero knowledge as to what to do with it because it will not have any contextual information appended to it.

10) Use finally blocks instead of catch blocks if you are not going to handle exception

try {
someMethod(); //Method 2
} finally {
cleanUp(); //do cleanup here
}

This is also a good practice. If inside your method you are accessing some method 2, and method 2 throw some exception which you do not want to handle in method 1, but still want some cleanup in case exception occur, then do this cleanup in finally block. Do not use catch block.

11) Remember “Throw early catch late” principle

This is probably the most famous principle about Exception handling. It basically says that you should throw an exception as soon as you can, and catch it late as much as possible. You should wait until you have all the information to handle it properly.

This principle implicitly says that you will be more likely to throw it in the low-level methods, where you will be checking if single values are null or not appropriate. And you will be making the exception climb the stack trace for quite several levels until you reach a sufficient level of abstraction to be able to handle the problem.

12) Always clean up after handling the exception

If you are using resources like database connections or network connections, make sure you clean them up. If the API you are invoking uses only unchecked exceptions, you should still clean up resources after use, with try -- finally blocks. Inside try block access the resource and inside finally close the resource. Even if any exception occur in accessing the resource, then also resource will be closed gracefully.

13) Throw only relevant exception from a method

Relevancy is important to keep application clean. A method which tries to read a file; if throws NullPointerException then it will not give any relevant information to user. Instead it will be better if such exception is wrapped inside custom exception e.g. NoSuchFileFoundException then it will be more useful for users of that method.

14) Never use exceptions for flow control in your program

We have read it many times but sometimes we keep seeing code in our project where developer tries to use exceptions for application logic. Never do that. It makes code hard to read, understand and ugly.

15) Validate user input to catch adverse conditions very early in request processing

Always validate user input in very early stage, even before it reached to actual controller. It will help you to minimize the exception handling code in your core application logic. It also helps you in making application consistent if there is some error in user input.

For example: If in user registration application, you are following below logic:

1) Validate User
2) Insert User
3) Validate address
4) Insert address
5) If problem the Rollback everything

This is very incorrect approach. It can leave you database in inconsistent state in various scenarios. Rather validate everything in first place and then take the user data in dao layer and make DB updates. Correct approach is:

1) Validate User
2) Validate address
3) Insert User
4) Insert address
5) If problem the Rollback everything

16) Always include all information about an exception in single log message

LOGGER.debug(“Using cache sector A”);
LOGGER.debug(“Using retry sector B”);

Don’t do this.

Using a multi-line log message with multiple calls to LOGGER.debug() may look fine in your test case, but when it shows up in the log file of an app server with 400 threads running in parallel, all dumping information to the same log file, your two log messages may end up spaced out 1000 lines apart in the log file, even though they occur on subsequent lines in your code.

Do it like this:

LOGGER.debug(“Using cache sector A, using retry sector B”);

17) Pass all relevant information to exceptions to make them informative as much as possible

This is also very important to make exception messages and stack traces useful and informative. What is the use of a log, if you are not able to determine anything out of it. These type of logs just exist in your code for decoration purpose.

18) Always terminate the thread which it is interrupted

while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {} //Don't do this
doSomethingCool();
}

InterruptedException is a clue to your code that it should stop whatever it’s doing. Some common use cases for a thread getting interrupted are the active transaction timing out, or a thread pool getting shut down. Instead of ignoring the InterruptedException, your code should do its best to finish up what it’s doing, and finish the current thread of execution. So to correct the example above:

while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
break;
}
}
doSomethingCool();

19) Use template methods for repeated try-catch

There is no use of having a similar catch block in 100 places in your code. It increases code duplicity which does not help anything. Use template methods for such cases.

For example below code tries to close a database connection.

class DBUtil{
public static void closeConnection(Connection conn){
try{
conn.close();
} catch(SQLException ex){
throw new RuntimeException("Cannot close connection", ex);
}
}
}

This type of method will be used in thousands of places in your application. Don’t put whole code in every place rather define above method and use it everywhere like below:

public void dataAccessCode() {
Connection conn = null;
try{
conn = getConnection();
....
} finally{
DBUtil.closeConnection(conn);
}
}

20) Document all exceptions in your application in javadoc

Make it a practice to javadoc all exceptions which a piece of code may throw at runtime. Also try to include possible course of action, user should follow in case these exception occur.

Exception (3) Java exception handling best practices的更多相关文章

  1. Exception (2) Java Exception Handling

    The Java programming language uses exceptions to handle errors and other exceptional events.An excep ...

  2. Java – Top 5 Exception Handling Coding Practices to Avoid

    This article represents top 5 coding practices related with Java exception handling that you may wan ...

  3. Java exception handling best practices--转载

    原文地址:http://howtodoinjava.com/2013/04/04/java-exception-handling-best-practices/ This post is anothe ...

  4. Java AOP nested exception is java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice || Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#0' 两个异常解决办法

    贴出applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...

  5. nested exception is java.lang.RuntimeException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps collection already contains value for

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'daoSupport': ...

  6. myeclipse启动tomcat会出现 a java exception has occured错误 的解决方法

    在浏览器中可以打开tomcat,结果在myeclipse启动tomcat会出现 a java exception has occured错误 ,之后出现一个Classloader.class的文件,关 ...

  7. Spring 整合 Flex (BlazeDS)无法从as对象 到 Java对象转换的异常:org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.util.Date' to required type 'java.sql.Timestamp' for property 'wfsj'; nested exception is java.lang.Ill

    异常信息如下: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value ...

  8. jedis:exception is java.lang.VerifyError: Bad type on operand stack

    项目中需要用到缓存,经过比较后,选择了redis,客户端使用jedis连接,也使用到了spring提供的spring-data-redis.配置正确后启动tomcat,发现如下异常: ======== ...

  9. Spring系列: 使用aop报错:nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$Refle

    写了个最简单的aop例子 配置文件如下 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ...

随机推荐

  1. 第七章 HTTP流量管理(一) gateway

    Gateway: istio的一种资源类型,Istio Gateway告诉k8s的istio-ingressgateway pods可以打开哪些主机和端口(如下的80是 ingressgateway ...

  2. 100.64.0.0/10运营商级(Carrier-grade)NAT保留IP地址

    在一次跟踪路由的网络操作时发现自己路由器下一跳路由节点的IP地址比较奇怪,是100.64.0.1.好奇促使我查询了这个IP地址的归属,结果是保留地址,到这里觉得比较奇怪了,按照常理以IPv4为例保留的 ...

  3. WebService与WCF

    5.Web Service和WCF的到底有什么区别 https://zhidao.baidu.com/question/1368120490988718179.html 6.VS 2010中使用C#创 ...

  4. keil中结构体跨文件调用

    在a.h中: 定义了, struct ABC{ short a; short b; ```}; 在a.c中(#include "a.h"): 声明了, struct ABC stc ...

  5. leetcode384

    public class Solution { private int[] nums; private Random random; public Solution(int[] nums) { thi ...

  6. 关于java中的OutOfMemory种类和解决方法

    1.OutOfMemory的三种情况 1) 永久区溢出 Exception in thread "main" java.lang.OutOfMemoryError: PermGen ...

  7. 查看DNS服务器

    电脑右键查看本地连接 查看状态 然后看DNS

  8. 用Python将word文件转换成html(转)

    用Python将word文件转换成html   序 最近公司一个客户大大购买了一堆医疗健康方面的科普文章,希望能放到我们正在开发的健康档案管理软件上.客户大大说,要智能推送!要掌握节奏!要深度学习!要 ...

  9. flutter 交互提示方式

    交互提示方式dialog和snackbar 首先看看dialog的方式 new PopupMenuButton( icon: new Icon(Icons.phone_iphone, color: C ...

  10. Set与List之间转化

    List list = new ArrayList(set);Set set = new HashSet(list); //但是有一点,转换当中可能要丢失数据,尤其是从list转换到set的时候,因为 ...