Java has been in the development world for a long time. Although several other languages have captured the market with much better features, Java is here to stay.
There is a lot to understand while learning Java, such as Java exceptions. An exception in Java is an event that disrupts the normal functioning of a program during execution. It can occur at compile time or run time and it can be of many types. These exceptions are unwanted and have a fundamental hierarchy.
Java exceptions Hierarchy explained
The Throwable class is at the top of the exception hierarchy following which are the subclasses-Error and Exception. Error and Exception should not be confused as same because there is a huge difference between these two classes.
Where an exception is an unwanted event in a program that can be handled within the program the error cannot be handled in a program as it is a much serious condition that causes damage to the architecture.
Examples of Exceptions:
IllegalArgumentException, ClassNotFoundException and NullPointerException.
Examples of Error:
InternalError, OutOfMemoryError and AssertionError.
Exceptions are of two types-checked and unchecked exceptions. Checked ones are the compile-time exceptions and unchecked are Runtime exceptions. Further subclasses of RuntimeException are unchecked and other than this are checked ones.
Let’s understand better about Java exceptions and errors better through examples:
In the example below the method “print” calls itself recursively until it reaches the maximum size of the Java thread. After reaching the maximum limit, it exits with a StackOverflowError:
public static void print(String myString) {
print(myString);
}
Exception in thread “main” java.lang.StackOverflowError
at StackOverflowErrorExample.print(StackOverflowErrorExample.java:6)
This is an error and it is not handled in the program or code because it cannot be debugged. The code or the program needs to change in this case.
Checked and unchecked exceptions
public void writeToFile() {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(“myFile.txt”))) {
bw.write(“Test”);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
In the above code, the statements written in the try block throw IOException. IOException is a checked exception, it is handled in the program itself and the exception stack trace is printed to the console, shown as below:
Exception in thread “main” java.lang.NullPointerException
at IOExceptionExample.writeToFile(IOExceptionExample.java:10)
at IOExceptionExample.main(IOExceptionExample.java:17)
Unchecked exceptions do not have to be handled in the code therefore NullPointerException here is not handled only IOException is handled.
Read Also: Top 7 Java Testing Frameworks for Enterprise Software
Learning Throwing exceptions in Java is equally important as handling these exceptions. This feature helps the developer to create quality code and make debugging easier.
Throwing an exception requires the use of ‘throw’ statement in the code. The exception object is mentioned which needs to be thrown with a message. This message contains a brief about the exception like user input issue, any server or backend related issue, etc.
Here’s how you can throw an exception:
throw new Exception(“Exception message”);
The throws keyword defines that the method is going to throw an exception Once the exception is thrown the caller has to handle it using a try-catch block. We can throw either checked or unchecked exceptions.
The throws keyword provides information about the type of exception that the method may throw but does not prevent the program from getting aborted.
In the example below, The toString() method calls on a null reference which is a NullPointerException.
static void testMethod() throws Exception {
String test = null;
test.toString();
}
How this exception is handled:
public class Example {
public static void main(String[] arg) {
try {
testMethod();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The Exception class
The developer must know how to create and throw an exception. This helps in using the exceptions more effectively.
The definition of the exception class goes like this- the superclass of all classes representing recoverable exceptions. The main goal of the exception class is to extend Throwable. The constructor depicts two parameters-on is detail Message that offers the details of the message for the exception that occurred and Throwable parameter offers the root cause of the exception.
Read Also: Things You Can Create with Java
Custom exceptions are basically to provide more control to the developer to explain the exception better to the user. The built-in exceptions in Java may not provide enough information, so the developer needs to add more to this information by customizing the exception. If the exception occurs during an ongoing program, the user needs to know about it. A custom exception is all about providing more data and making the explanation clear.
So, in Java, how do developers customize exceptions? The best answer is by extending the java.lang. Exception class with a new class. This new class requires a parent class constructor to hold the error.
To understand custom exception better here’s an example-suppose there’s a program that has an issue in connecting to the database, in this custom exception can be used. This exception will have the details such as the database URL, username, password, etc. Whereas the catch block can have customized information with a simple readable message for the user saying that the program has failed to connect to the database.
Handling Exceptions in Java
Exception handling in Java is important to maintain the normal flow of the program even during the occurrence of unexpected events. If the exceptions are not handled, they will lead to the crashing of the app resulting in frustrated customers. If applications that use important user data crash while the user is working, it leads to a huge customer churn. The unexpected crashing of the application may lead to data loss.
To avoid such situations there is a need for exception handling. System crashes may occur when a user inputs wrong data again and again or in case of incorrect data. In these cases, the developers must throw an exception instead of letting the system crash.
It is quite predictable by the developers that how many exceptions a Java piece of code can throw. For the smooth functioning of a program, the best tactic is to explicitly handle the exceptions and recover from the unwanted event seamlessly. There are many cases when exceptions cannot be predicted, such exceptions are called unhandled exceptions. These can also be tracked by letting the developers check the code quality and proper visibility of the entire program such that these exceptions can be avoided.
Developers know that exceptions happen in all codes or set of programs no matter how perfect the coding is. Therefore, there is a procedure for tracking all the Java exceptions by maintaining a record in the application log file. This log file is of great help to the current developers as they can easily open the file and track all the exceptions that the program has gone through. This standard procedure is applicable for small scale applications but not exactly for the large enterprise software. The manual analysis for tracking the errors in large scale applications leads to loss of track, incorrect analysis and ultimately no resolution. Therefore, the need for error monitoring software comes into existence. This software reduces manual efforts by categorizing the duplicates and reporting a brief summary of the latest errors to the developers. These automated tools are very helpful in streamlining the data that’s much easier to understand.
For small-scale applications, going through a log file is easy. However, enterprise applications can serve thousands or even millions of requests per second. This makes manual analysis too cumbersome because errors and their causes can be lost in the noise. This is where error monitoring software can help by grouping duplicates and providing summarized views of the top and most recent Java errors. They can also capture and organize contextual data in a way that’s easier and faster than looking at logs.
There are specific Java exceptions too which the developers can catch in a code. This involves a dedicated code to recover. For instance, A few Java errors returned from a REST API can be recovered but some cannot be recovered at all, so, to catch the recoverable exceptions you will have to treat them separately.
A try-catch method is the best way to handle exceptions. To catch specific Java exceptions a try block can be followed by one or more catch blocks, each specifying a particular type. If there’s an exception in the try block, the exception is thrown to the first catch block, if not caught by this class it is passed on until it gets caught or misses all.
The finally block is for the code that is to be executed in every case, whether there is an exception or not. It means the finally block is executed every time.
Uncaught or runtime exceptions can happen anytime and in any code. The developer does not get any warning or signal that these exceptions may occur or not. Java offers a perfect way to handle runtime exceptions like these. You can set an UncaughtExceptionHandler in every thread and catch such unpredictable exceptions.
Java is a vast language, to become an expert there are a lot many things a Java developer must know. Handling and Throwing exceptions are such features that you should integrate with programs to make the program and the resulting app user-friendly. The above details and information make it quite obvious that learning exceptions in Java is important and a whole new topic to being a good Java developer. Managing, tracking, and handling exceptions can be challenging many times. You should manage all the exceptions in real-time and improve the user experience.
Also Published here