Java Exception in detail with example

Let’s start the topic with what is an Exception?

Exceptions are unexpected events that occur during the execution of a program. An exception might result due to an unavailable resource, unexpected input from a user, or simply a logical mistake by the programmer. In Java, exceptions are objects that can be thrown by code that encounters an unexpected situation, or by the Java Virtual Machine. For example, if JVM running out of memory. An exception may also be caught by a surrounding block of code that “handles” the problem in an appropriate way. If uncaught, an exception causes the virtual machine to stop executing the program and print an appropriate message with the root cause to the console.

Catching Exceptions:

If an exception occurs and is not handled by the programmer, then the Java run-time will terminate the program after printing an appropriate message together with a trace of the run-time stack. The stack trace shows the series of nested method calls that were active at the time the exception occurred, as in the following example:

Exception in thread "main" java.lang.NullPointerException
at com.exception.AllAboutException.main(AllAboutException.java:31)

However, before a program is terminated, each method on the stack trace has an opportunity to catch the exception. Starting with the method in which the exception occurs. Each method may either catch the exception or allow it to pass through to the method that called it. This is also known as exception propagation.

The usual way of exception handling is a try-catch construct in which a snippet of code that might throw an exception is executed. If it throws an exception, then that exception caught by a predefined catch block. That catch block contains the code to analyze the exception and apply an appropriate resolution. If no exception occurs in that code snippet inside the try block, all catch blocks are ignored.

The typical syntax for a try-catch block in Java is as follows:

try {
/.. code snippet

} catch (exceptionType1  e1) {

// TODO::

} catch (exceptionType2  e2) {
// TODO::
*
}
/…

Let’s changes the code that caused java.lang.NullPointerException, by putting it inside a try-catch block as below.

public class AllAboutException {
    
    public static void main(String[] args) {
        Object obj = null;
        try {
            System.out.println(obj.toString());
        }catch (Exception e) {
            System.out.println(" Exception during execution obj is: "+ obj);
            
        }
    }
} 

Again run the above code, this time it will only print the message “exception during execution obj is: null“.

Try with Multiple catch block:

Similar to above we can have multiple catch blocks for a try block. The point to be remembered is that the order of the catch block should be most relevant to most generic. Consider the following example.

public class AllAboutException {
        
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            
            if(a < 0) {
                a = 10;
                System.out.println("default value of a is "+a);
            }
            else
                System.out.println("value received of a is "+a); 
            
        }
        catch (ArrayIndexOutOfBoundsException ae) {
            System.out.println(" no argument passed to main ");
        }catch (NumberFormatException ne) {
            System.out.println(" the argument passed to main is not a valid integer");
        }catch (Exception e) {
            System.out.println("Error while processing.");
        }

    }
}

Multi Catch

Since Java 7 it was made possible to catch multiple different exceptions in the same catch block. It is often known as multi-catch. By applying this concept we can change the above catch block like below:

 
catch (ArrayIndexOutOfBoundsException | NumberFormatException | Exception e) {
        System.out.println(" Error while processing.");
}

Finally:

Writing the code inside the try-catch block is fine to avoid unintended execution of programs. But what if you have to perform some task even if there is an exception?

In those cases, we can use the finally block, which executes whether there is an exception or not.

The key point while writing the code inside a try:

A try block must be followed by at least one catch block or by a finally block. We can have both as well. Refer to the code snippet.

public class AllAboutException {
        
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            
            if(a < 0) {
                a = 10;
                System.out.println("default value of a is "+a);
            }
            else
                System.out.println("value received of a is "+a); 
            
        }
        catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
            System.out.println("Error in execution");
        }
        finally {
            System.out.println("Finally block after catch ");
        }
    }
}

If you run the above program the output will be as below:

Error in execution
Finally block after catch   

So, enough reading about Exception, let’s take a simple test and see if you could answer it correctly.

Throwing Exceptions:

Exceptions occur when a chunk of Java code finds some problem during execution and throws an exception object. This is done by using the throw keyword followed by an instance of the exception type to be thrown, as follows:

throw new exceptionType(message);

Where the exception type is the type of exception and the message is the parameters sent to the constructor.

public class AllAboutException {
        
    public static void main(String[] args) {
        
        isPositiveInt(-1);
        
    }
    
    public static boolean isPositiveInt(int a) {
        if( a < 0) {
            throw new IllegalArgumentException(" only positive int allowed");
        } 
        return true;
    }
}
 
<strong>Output:</strong>

Exception in thread "main" java.lang.IllegalArgumentException:  only positive int allowed
    at com.exception.AllAboutException.isPositiveInt(AllAboutException.java:157)
    at com.exception.AllAboutException.main(AllAboutException.java:151)

Note: The execution of a throw statement immediately terminates the body of a method.

The Throws Clause

Java allows us to declare exceptions as part of its method signature, which is achieved using the throws clause. The possibility that a particular exception may be thrown during a call to that method. It does not matter whether the exception is directly from a throw statement in that method body, or propagated upward from a method call made from within the body of the method itself.

The syntax for declaring possible exceptions in a method signature relies on the keyword throws. For example, the parseInt method of the Integer class has the following formal signature:

public static int parseInt(String s) throws NumberFormatException;

The ‘throws NumberFormatException’ warns the caller of that method about the possibility of an exception if the inputs are not valid so that they might be better prepared to handle an exception that may arise. If more than one exception requires to be thrown, all such types can be listed, separated with commas.

Java Exception Hierarchy:

Java provides an inheritance hierarchy of all objects that are deemed Throwable. The exception hierarchy is divided into two subclasses, Error and Exception.

Errors are typically thrown only by the Java Virtual Machine and designate the most severe situations that are unlikely to be recoverable, such as when the system runs out of memory. On the other hand, exceptions designate situations in which a running program might be able to recover or can be handled using a try-catch block, for example, like files not found, etc.

Further to this Exceptions are categories in two categories:

  • Checked Exception
  • Unchecked Exception

All subclasses of RuntimeException in Java are officially treated as unchecked exceptions, and any exception type that is not part of the RuntimeException is a checked exception.

Exeption Hierarchy

Recommended read:
How to create custom Java Exception?
Java try with resources statement

Reference:
https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html

Happy Learning !!

Leave a Comment