Last Updated:

A Complete Guide to Exception Handling in Java

 

Exception handling in Java. Synopsis

An exception can occur in various situations: incorrect input data, hardware failure, network connection failure, error when working with the database, etc. That is why any Java programmer should be able to correctly handle exceptions, understand the reasons for their occurrence and follow the best practices for working with exceptions even in small projects.

Java is an object-oriented programming language, so whenever an error occurs while executing an instruction, an exception object is thrown, and then the normal run of the program stops and the JRE tries to find someone who can handle the exception. The exception object contains a lot of debugging information, namely the line number where the exception occurred, the type of exception, and so on.

What and how happens when an error appears

When an exception occurs in a method, the process of creating an exception object and passing it to the Runtime Environment is called throwing an exception.

After the exception is thrown, the Java Runtime Environment tries to find the exception handler.

An exception handler is a block of code that can handle an exception object.

The logic of finding an exception handler is simple - first of all, you start looking in the method where the error occurred, if the corresponding handler is not found, then you go to the method that calls this method, and so on.

Example

We have 3 methods, each of which calls each other: (A calls B, and B calls C). If an exception appears in method C, then the search for the corresponding handler will occur in reverse order: (first, where there was an exception - in C, if there is no handler, then go to method B - if there is also no, then go to A).А -> В -> СС -> В -> А

If a matching exception handler is found, the exception object is passed to the handler.

To handle an exception is to "catch an exception."

If no exception handler is found, the program shuts down and prints the exception information.

Note that exception handling in Java is a framework that is only used to handle run-time errors. Compilation errors are not handled as part of exception handling.

Key Elements of Exception Handling in Java

We use certain keywords in to create an exception handling block. Let's look at them with an example. We will also write a simple program for handling exceptions.

  • Throw an exception is a keyword that is used to throw an exception at run time. We know that the Java Runtime starts looking for an exception handler as soon as it is thrown, but often we ourselves need to throw an exception in our code, for example, in the authorization program, if some field is . It is for such cases that it is possible to throw an exception.null
  • throws - When we throw an exception in a method and don't handle it, we must use a keyword in the method signature to throw an exception for processing in another method. The calling method can handle this exception or throw it even further by using the method signature. It should be noted that several exceptions can be dropped at once.throwsthrows
  • The block is used to handle exceptions in code. The word is the beginning of the processing block, the end of the block for handling exceptions. We can use several blocks at once with one . takes the type of exception to be handled as a parameter.try-catchtrycatchcatchtrycatch
  • finally is the optional final design of the block. Once the exception has stopped the program execution process, we can safely free up some open resources. It should be noted that the block is always executed - despite the emergence of an exceptional situation.try-catchfinallyfinally

Let's look at a simple exception handling program in Java.

And in the console, this program will write this:

Note that the method throws an exception using the keyword , and the method signature uses the keyword to make it clear to the calling method the type of exceptions that the .testException()throwthrowstestException()

Important points in exception handling:

  • You cannot use blocks or without a block.catchfinallytry
  • A block can also be used only with a block, or only with a block, or with both blocks.trycatchfinally
  • We can use multiple blocks with only one .catchtry
  • try-catch blocks can be nested - in this way they are very similar to constructions.if-else
  • We can only use one, block in one.finallytry-catch

Exception hierarchy in Java

Java exceptions are hierarchical, and inheritance is used to categorize different types of exceptions. is a parent class in the Java exception hierarchy. It has two child objects, and . The exceptions are further divided into verifiable and run-time exceptions.ThrowableErrorException

  1. An error is a type of error that is outside the scope of your program and cannot be predicted or handled. This could be a hardware failure, a JVM crash, or a memory error. It is for such unusual situations that there is a separate hierarchy of errors. We just need to know that there are such mistakes and we cannot cope with such situations. Examples: and .ErrorOutOfMemoryErrorStackOverflowError
  2. Checked Exceptions are a type of exceptions that we can anticipate in a program and try to handle, such as . We need to catch this exception and write a clear and useful message to the user about what happened (it is also advisable to log errors). is the parent class of all Checked Exceptions. If we throw a checked exception, we should catch it in the same method or we should throw it with the keyword.FileNotFoundExceptionExceptionthrows
  3. Runtime Exceptions are programmer errors. For example, when trying to get an element from an array, we have to check the length of the array before trying to get the element — otherwise it might be thrown. is the parent class for all Runtime exceptions. If we throw the Runtime Exception in the method ourselves, then it is not necessary to specify the keyword in the method signature.ArrayIndexOutOfBoundExceptionRuntimeExceptionthrows

Figure 1 shows the hierarchy of exceptions in Java:

hierarchy of exceptions in Java

Figure 1 — Exclusion Hierarchy in Java

Useful methods in exception handling

The class and all of its subclasses do not contain any methods for handling exceptions. All the methods provided are in the base class. Class subclasses are designed to define different kinds of exceptions. That is why when handling exceptions, we can easily determine the cause and handle the exception according to its type.ExceptionThrowableException

Useful methods of the class:Throwable

  1. public String getMessage() - This method returns the message that was generated when the exception was thrown through the constructor.
  2. public String getLocalizedMessage() is a method that overrides subclasses to localize a specific exception message. In the class implementation, this method simply uses the method to return an exception message (at the top of the hierarchy — it has nothing to localize, so it calls .ThrowablegetMessage()ThrowablegetMessage())
  3. public synchronized Throwable getCause() — This method returns the cause of the exception or an identifier in the form of if the cause is unknown.null
  4. public String toString() — This method returns information about in the format .ThrowableString
  5. public void printStackTrace() – This method outputs stack trace information to a standard error stream, this method is overloaded and we can pass either as an argument to write stack trace information to a file or stream.PrintStreamPrintWriter

Automatic resource management and error block improvements in Java 7

If you need to catch a lot of exceptions in one block, then the interception block will look very ugly and will mostly consist of redundant code. That is why in Java 7 this has been greatly improved and now we can catch multiple exceptions in one block.try-catchcatch

It looks like this:

As you can see, here the block intercepts several exceptions at once - it is very beautiful, compact and convenient.catch

In most cases, we use a block to close open threads, connections, or release other resources. Very often we forget to close and get runtime exceptions. Such exceptions are difficult to debug. Therefore, Java 7 has been introduced with resources where we can open the resource in itself and use it inside the . When a program finishes executing a block, the runtime automatically closes these resources. Here's an example of a block with resources:finallytrytrytry-catchtry-catchtry-catch

Create your own exception classes

Java provides many exception classes, but sometimes we may need to create our own "custom" exception classes. This may be necessary in order to notify the subscriber of a specific type of exception with an appropriate message. For example, we'll write a method to handle only text files, so we can write our own exception class and pass the appropriate error code when someone passes the wrong file type as input.

Here's an example of your exception class and how to use it:

Now let's check our MyException class:

package com.p-qc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class CustomExceptionExample {
public static void main(String[] args) throws MyException {
try {
processFile("file.txt");
} catch(MyException e) {
processErrorCodes(e);
}

}


// error handling method
private static void processErrorCodes(MyException e) throws MyException {
// here we look for the error code specified when the exception was thrown and tell the user what happened
switch(e.getErrorCode()){
case "BAD_FILE_TYPE":
System.out.println("Wrong file type");
throw e;
case "FILE_NOT_FOUND_EXCEPTION":
System.out.println("File not found");
throw e;
case "FILE_CLOSE_EXCEPTION":
System.out.println("Error closing file");
break;
default:
System.out.println("An unknown error occurred " + e.getMessage());
e.printStackTrace();
}
}
// method for working with a file that throws our exception type
private static void processFile(String file) throws MyException {
InputStream fis = null;
try {
fis = new FileInputStream(file);
} catch(FileNotFoundException e) {
// here we throw an exception with an error code
throw new MyException(e.getMessage(),"FILE_NOT_FOUND_EXCEPTION");
}finally{
try {
if(fis !=null)fis.close();
} catch (IOException e) {
// here we throw an exception with an error code
throw new MyException(e.getMessage(),"FILE_CLOSE_EXCEPTION");
}
}
}
}

Useful Tips for Handling Exceptions in Java

  1. Do not use the Exception class to catch exceptions. In the hierarchy of exceptions, there are many classes for all cases of your program that will not only effectively handle a specific error, but also provide useful information for the user and debugging.
  2. Throw an exception as early as possible. This is a good practice of programming in Java.
  3. Catch exceptions only when you can handle them efficiently for the user and debug them.
  4. Free up resources. When catching an exception, always close open resources. It's even easier and more efficient to do this with . Use try with resources for concise and beautiful code.Java 7
  5. Log exceptions. Log messages that the exception provides. In most cases, this will give you a clear understanding of the causes and help with debugging. Don't leave the block blank, otherwise it will just absorb the exception without any meaningful details to debug.catch
  6. One catch for multiple exceptions. Take advantage of Java 7 for the convenience and beauty of your code.
  7. Use your exceptions. This will allow you to feel your program better and work with it more effectively.
  8. Naming conventions. When you create your exception classes, make sure that it's clear from the class name itself that it's an exception.
  9. Use exceptions wisely. Throwing an exception is quite an expensive operation in Java. Perhaps, in some cases, it will be appropriate not to throw exceptions, but to return, for example, a Boolean variable that indicated the success or failure of the execution of the method.
  10. Document exceptions. It is advisable to write javadoc @throws for your exceptions. This will be especially useful in cases where your program provides an interface for working with other applications.

That's all you need to know about exception handling in Java.