Exception

In java, when a program errors out, it generates an Exception to the user to indicate what went wrong. There are two types of Exception, checked Exception and un-checked Exception. In java, everything is an object and hence, Exception is also an Object. Below is the Exception hierarchy:

exception hierarchy

Any class that extends Exception is considered a checked Exception(except for RuntimeException) and anything that extends RuntimeException is considered un-checked. So what actually is the difference between the two?

  • Un-checked Exceptions – These are the Exceptions you probably encountered more often at this point, for example, NullPointerException, IndexOutOfBoundsException, these are errors that is typically the programmer’s fault. In other words, the program failed because of a logic flaw in your code. Somehow your program is accessing index at 10 while you only have a length of 9; or somehow your program is trying to call a method on a null value and errors out. Both of these cases can be avoided with good code.
  • Checked Exceptions – These are problems that is usually un-preventable from the coder, it is an error that no matter how good your code is, you cannot prevent that from happening. For example, you are running a java program on your USB drive and everything is running fine. Suddenly, your little brother comes into your room and snatches your USB away because…uhhh… just because. You looked at your computer, all of a sudden, your program doesn’t know where to find code to run anymore because the USB is un-plugged. This is a situation that is unforeseen by the programmer. Another example is a typical situation where the program tries to open a file on your computer. Let’s say that program A is looking for a file named “openMe.txt”, but nowhere on your computer does openMe.txt exists. The program fails because the user fails to satisfy the condition not because the coder left a bug in the program. In other words, there is no way for the coder to prevent such event from happening. These kinds of errors are usually considered checked exceptions.

If Java detects that your program has a possibility of throwing a checked Exception, Java will require the developer(you) to either handle the exception, or put a throws tag at the method header to let other methods handle the exception. If neither are done, then your code will not compile. Before we dive into how to cope with checked exception, let us discuss what it means to “handle the exception” and “put a throws tag at method header”.

Handle the exception: Try-catch-finally trifecta

The syntax for a try-catch-finally statement is as follows:

            try{
                //some code here
            } catch ([SomeException] variableName){
                //code to run if exception happens
            } finally{
                //this part of the code ALWAYS runs regardless if the program errors out
            }
        

When the program runs, it first executes the code in the try block, if no exception occurred, the catch blocks will not be executed. If an exception occurred, Java checks whether this exception object is caught in the catch block. If it is caught, the catch block will be executed; if it is not caught, the program will jump to the caller of the method until it is caught or reach main method which the program errors out.

You can chain a series of catch blocks to catch different Exceptions. For example:

            try {
                //some code here
            } catch (IllegalArgumentException e){
                //some code here
            } catch(NullPointerException n){
                //some code here
            } catch(IOException i){
                //some code here
            }
        

There is a rule while chaining catch blocks, consider the following:

            try{
                //some code here
            } catch (Throwable t){
                //part 1 code
            } catch (FileNotFoundException f){
                //part 2 code
            }
        

Only one catch block will be accessed in a try-catch statement, if at all. Because Throwable is at the top of hierarchy of all Exceptions, FileNotFoundException is-a Throwable. Hence even if FileNotFoundException occurred in try block, only part 1 code will be executed. Moreover, if FileNotFoundException somehow occurred while executing part 1 code, part 2 code will still not be executed. In a nutshell, part 2 of the code will never be executed no matter what happens in try block or catch block. Hence, part 2 code are considered unreachable code or dead code and that causes compilation error.

In order to solve this issue, you will need to build the catch block series starting from the most specific exception and move to the more general exception.

            try{
                //some code here
            } catch (FileNotFoundException e){
                //part 1 code
            } catch (Throwable t){
                //part 2 code
            }
        

The above try-catch block fixes the error and compiles.

Throws

The throws clause acts like a warning tag, it tells the user that the method is capable of generating a certain exception. It passes on the responsibility to cope with the exception to other methods. For example:

             public static void inputFile(String filename) throws FileNotFoundException {
                //Somewhere in the body of the code might generate FileNotFoundException
             }
        

By looking at the header without scanning the body of the method, we know that the method is capable of throwing a FileNotFoundException, and whoever uses the method needs to cope with the exception. Consider the following example:

            public static void main(String[] args){
                inputFile(“Text.txt”);
            }
        

Looking at the body of main method, there aren’t any Exception being generated, but because in the method header of inputFile, there is a warning tag throws telling main method that inputFile might generate a FileNotFoundException which is a checked exception. Hence, main method now has to cope with this checked exception, either handle this checked exception or put a throws tag in the method header. It is noteworthy that the main method above will not compile.

Throws is usually used in combine with checked exception, you can, however, put a unchecked exception with the throws clause, it has no effect though.

How do we make it compile? Again, we can either choose to handle the exception or put a throws tag at the header, let us try both of the approaches.

Handle the exception
           public static void main(String[] args){
                try{
                      inputFile(“Text.txt”);
                } catch(FileNotFoundException e){
                      System.out.println(“caught an error”);
                }
                System.out.println(“Continue running”);
            }
        
Put a throws tag

            public static void main(String[] args) throws FileNotFoundException{
                inputFile(“Text.txt”);
            }
        

Note: Although this would make the code compile, it is usually a bad practice to put throws in the main method header, because if the Exception is generated, your program crashes, and that never is a good thing to happen.

There is another keyword that people usually confuse with throws and that is “throw”.

Throw

The throws keyword indicates that you want to generate an exception in your program, usually indicating that something is wrong. The syntax of generating an exception in your program is

            throw new [Exception Object]
        

Just about everything in java is an Object, Exception is also an Object, thus to create an Exception, you need the new keyword as well.

For example, you design a program that errors out when a parameter of the method takes in a negative number.

            public void checkNegative(int number){
                if(number < 0){
                    throw new IllegalArgumentException(“Number cannot be negative”);
                }
            }
        
Exception tracing

A method stops when it hits an exception and immediately start looking for exception handling – catch blocks. If it does not find it in the current method, it will go to whichever method called the current method and look for a catch block until it does, or crashes.

Custom Exception

In above section, we know that exceptions are object, so can we create our own exception? Of course. You would create a class like any object but extends Exception object if you want a checked exception, and extends RuntimeException object if you want a unchecked exception.

Making it checked
             public class MyException extends Exception{
                //…
             }
        
Making it unchecked
            public class MyException extends RuntimeException{
                //…
            }
        

You can also add more constructors or instance variable to make your custom exception perform certain action. For example if you want your custom exception to take in an error message, you can put a String parameter in the constructor like the following.

        public class MyException extends Exception{
            public MyException(String msg){
                super(msg);
            }
        }
        

Note this is the standard way to create an exception that takes in a string error message, you can of course create a instance variable to hold the error message, but you shouldn’t reinvent the wheels when you don’t have to.

Practice makes perfect

            public static void main(String[] args) {
                try {
                    System.out.println(“Let’s begin”);
                    method1();
                    System.out.println(“Exception occurred”);
                } catch(IllegalArgumentException i) {
                    System.out.println(“Caught an Exception”);
                } finally{
                    System.out.println(“Should I run finally?”);
                }
                    System.out.println(“Am I still running?”);
                }
            public static void method1() {
                System.out.println(“I’m in method 1”);
                throw new IllegalArgumentException(“I errored out”);
            }