Java error handling methods



Top 20 Java Exception Handling Best Practices

Last Updated: December 26, 2020

This post is another addition in best practices series available in this blog. In this post, I am covering some well-known and some little known practices which you must consider while handling exceptions in your next java programming assignment. Follow this link to read more about exception handling in java.

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.

1. Type of exceptions in Java

Checked exceptions

These 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

These 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.

2. 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 ) 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
  2. Or wrap the original exception inside custom exception and throw it

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.

3. Java exception handling best practices you must consider and follow

3.1. Never swallow the exception in catch block

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 !!

3.2. Declare the specific checked exceptions that your method can throw

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.

3.3. Do not catch the Exception class rather catch specific sub classes

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.

3.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.

3.5. Always correctly wrap the exceptions in custom exceptions so that stack trace is not lost

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

3.6. Either log the exception or throw it but never do the both

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.

3.7. Never throw any exception from finally block

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.

Читайте также:  Вместо пробега горит error

3.8. Always catch only those exceptions that you can actually handle

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.

3.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.

3.10. Use finally blocks instead of catch blocks if you are not going to handle exception

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.

3.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.

3.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.

3.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.

3.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.

3.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

3.16. Always include all information about an exception in single log message

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:

3.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.

3.18. Always terminate the thread which it is interrupted

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:

Читайте также:  Что значит host error recursively entered

3.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.

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:

3.20. Document all exceptions in the application with 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.

That’s all i have in my mind for now related to Java exception handling best practices. If you found anything missing or you does not relate to my view on any point, drop me a comment. I will be happy to discuss.

Источник

Exceptions in Java

Exception Handling in Java is one of the effective means to handle the runtime errors so that the regular flow of the application can be preserved. Java Exception Handling is a mechanism to handle runtime errors such as ClassNotFoundException, IOException, SQLException, RemoteException, etc.

Exception is an unwanted or unexpected event, which occurs during the execution of a program, i.e. at run time, that disrupts the normal flow of the program’s instructions. Exceptions can be caught and handled by the program. When an exception occurs within a method, it creates an object. This object is called the exception object. It contains information about the exception, such as the name and description of the exception and the state of the program when the exception occurred.

Major reasons why an exception Occurs

  • Invalid user input
  • Device failure
  • Loss of network connection
  • Physical limitations (out of disk memory)
  • Code errors
  • Opening an unavailable file

Errors represent irrecoverable conditions such as Java virtual machine (JVM) running out of memory, memory leaks, stack overflow errors, library incompatibility, infinite recursion, etc. Errors are usually beyond the control of the programmer, and we should not try to handle errors.

Let us discuss the most important part which is the differences between Error and Exception that is as follows:

  • Error: An Error indicates a serious problem that a reasonable application should not try to catch.
  • Exception: Exception indicates conditions that a reasonable application might try to catch.

Exception Hierarchy

All exception and error types are subclasses of class Throwable, which is the base class of the hierarchy. One branch is headed by Exception. This class is used for exceptional conditions that user programs should catch. NullPointerException is an example of such an exception. Another branch, Error is used by the Java run-time system(JVM) to indicate errors having to do with the run-time environment itself(JRE). StackOverflowError is an example of such an error.

Types of Exceptions

Java defines several types of exceptions that relate to its various class libraries. Java also allows users to define their own exceptions.

Exceptions can be categorized in two ways:

  1. Built-in Exceptions
    • Checked Exception
    • Unchecked Exception
  2. User-Defined Exceptions

Let us discuss the above-defined listed exception that is as follows:

A. Built-in Exceptions:

Built-in exceptions are the exceptions that are available in Java libraries. These exceptions are suitable to explain certain error situations.

  • Checked Exceptions: Checked exceptions are called compile-time exceptions because these exceptions are checked at compile-time by the compiler.
  • Unchecked Exceptions: The unchecked exceptions are just opposite to the checked exceptions. The compiler will not check these exceptions at compile time. In simple words, if a program throws an unchecked exception, and even if we didn’t handle or declare it, the program would not give a compilation error.

Note: For checked vs unchecked exception, see Checked vs Unchecked Exceptions

B. User-Defined Exceptions:

Sometimes, the built-in exceptions in Java are not able to describe a certain situation. In such cases, users can also create exceptions, which are called ‘user-defined Exceptions’.

The advantages of Exception Handling in Java are as follows:

  1. Provision to Complete Program Execution
  2. Easy Identification of Program Code and Error-Handling Code
  3. Propagation of Errors
  4. Meaningful Error Reporting
  5. Identifying Error Types

Methods to print the Exception information:

1.printStackTrace()– This method prints exception information in the format of Name of the exception: description of the exception, stack

Output:

2.toString() – This method prints exception information in the format of Name of the exception: description of the exception.

Output:

3.getMessage() -This method prints only the description of the exception.

Output:

How Does JVM handle an Exception?

Default Exception Handling: Whenever inside a method, if an exception has occurred, the method creates an Object known as an Exception Object and hands it off to the run-time system(JVM). The exception object contains the name and description of the exception and the current state of the program where the exception has occurred. Creating the Exception Object and handling it in the run-time system is called throwing an Exception. There might be a list of the methods that had been called to get to the method where an exception occurred. This ordered list of the methods is called Call Stack. Now the following procedure will happen.

  • The run-time system searches the call stack to find the method that contains a block of code that can handle the occurred exception. The block of the code is called an Exception handler.
  • The run-time system starts searching from the method in which the exception occurred, and proceeds through the call stack in the reverse order in which methods were called.
  • If it finds an appropriate handler, then it passes the occurred exception to it. An appropriate handler means the type of the exception object thrown matches the type of the exception object it can handle.
  • If the run-time system searches all the methods on the call stack and couldn’t have found the appropriate handler, then the run-time system handover the Exception Object to the default exception handler, which is part of the run-time system. This handler prints the exception information in the following format and terminates the program abnormally.
Читайте также:  What is runtime error 217

Look at the below diagram to understand the flow of the call stack.

Illustration:

Output:

Let us see an example that illustrates how a run-time system searches for appropriate exception handling code on the call stack.

Example:

How Programmer Handles an Exception?

Customized Exception Handling: Java exception handling is managed via five keywords: try, catch, throw, throws, and finally. Briefly, here is how they work. Program statements that you think can raise exceptions are contained within a try block. If an exception occurs within the try block, it is thrown. Your code can catch this exception (using catch block) and handle it in some rational manner. System-generated exceptions are automatically thrown by the Java run-time system. To manually throw an exception, use the keyword throw. Any exception that is thrown out of a method must be specified as such by a throws clause. Any code that absolutely must be executed after a try block completes is put in a finally block.

Need for try-catch clause(Customized Exception Handling)

Consider the below program in order to get a better understanding of the try-catch clause.

Example:

Output:

Output explanation: In the above example, an array is defined with size i.e. you can access elements only from index 0 to 3. But you trying to access the elements at index 4(by mistake) that’s why it is throwing an exception. In this case, JVM terminates the program abnormally. The statement System.out.println(“Hi, I want to execute”); will never execute. To execute it, we must handle the exception using try-catch. Hence to continue the normal flow of the program, we need a try-catch clause.

How to Use the try-catch Clause?

Certain below key points are needed to be remembered that are as follows:

  • In a method, there can be more than one statement that might throw an exception, So put all these statements within their own try block and provide a separate exception handler within their own catch block for each of them.
  • If an exception occurs within the try block, that exception is handled by the exception handler associated with it. To associate the exception handler, we must put a catch block after it. There can be more than one exception handlers. Each catch block is an exception handler that handles the exception to the type indicated by its argument. The argument, ExceptionType declares the type of exception that it can handle and must be the name of the class that inherits from the Throwable class.
  • For each try block, there can be zero or more catch blocks, but only one final block.
  • The finally block is optional. It always gets executed whether an exception occurred in try block or not. If an exception occurs, then it will be executed after try and catch blocks. And if an exception does not occur, then it will be executed after the try block. The finally block in java is used to put important codes such as clean up code e.g., closing the file or closing the connection.

The summary is depicted via visual aid below as follows:

Related Articles:

This article is contributed by Nitsdheerendra and Gaurav Miglani. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Related Courses

Java Programming Foundation – Self Paced Course

Find the right course for you to start learning Java Programming Foundation from the industry experts having years of experience. This Java Programming Foundation – Self Paced Course covers the fundamentals of the Java programming language, data types, operators and flow control, loops, strings, and much more. No more waiting! Start Learning JAVA Now and Become a Complete Java Engineer!

Источник

Оцените статью
toolgir.ru
Adblock
detector