Wednesday, June 18, 2025

Exceptions

 Things go wrong in Java all the time, especially in more complex systems, or when user input is required: data is entered incorrectly, or a file is sent in the wrong format, or you keep looping beyond where there is no more material to consume—the list of potential bugs is endless.


Exception handling is a fundamental concept in Java that allows you to manage errors gracefully and keep your program running even when unexpected issues occur. The basic structure involves three main keywords: try, catch, and finally. The try block contains code that might throw an exception—essentially, code that could go wrong at runtime. For example, if you try to divide a number by zero inside a try block, Java will throw an ArithmeticException. When an exception occurs, the normal flow of the program is interrupted, and control jumps to the catch block, which is designed to handle specific types of exceptions. In the case of dividing by zero, the catch block can print an error message or take corrective action, ensuring the program doesn’t crash abruptly. Perhaps, after the printing of the error message, the user can be invited to try to input a number again, this time trying consciously to avoid whatever the exception was.

Let’s look at a simple try-catch:

public class TryCatchExample {

    public static void main(String[] args) {

        try {

            int result = 10 / 0; // This will throw ArithmeticException

            System.out.println("Result: " + result);

        } catch (ArithmeticException e) {

            System.out.println("Error: Cannot divide by zero!");

        }

        System.out.println("Program continues after the try-catch block.");

    }

}

We enter the try-block, and attempt to assign 10/0 into an integer. Just as in math, in Java, you cannot divide by 0 without causing problems. (I don’t know if Java is actually trying to “divide” by zero somehow, the process is running away, and it’s throwing in the towel, or if Java has simply been written in a way such that “if someone tries to divide by 0, don’t even entertain that—just throw an error ASAP.”) In any case, dividing by zero throws an error, which, if not handled properly (by a catch-block, for example), will crash the program.

The finally block is optional but highly useful. Code inside finally will always execute, regardless of whether an exception was thrown or caught. This makes it ideal for cleanup actions, such as closing files or releasing resources. For instance, even if an exception occurs while reading a file or dividing numbers, the finally block can still close the file or print a message, guaranteeing that essential cleanup steps are performed. 

public class TryCatchFinallyExample {

    public static void main(String[] args) {

        try {

            int result = 10 / 0; // This will throw ArithmeticException

            System.out.println("Result: " + result);

        } catch (ArithmeticException e) {

            System.out.println("Error: Cannot divide by zero!");

        } finally {

            System.out.println("This is the finally block. It always runs.");

        }

        System.out.println("Program continues after the try-catch-finally block.");

    }

}

Consider this simple example: inside the try block, you attempt to divide by zero (exactly like the previous example above); the catch block prints out the exception message (again, exactly the same), and the band-new finally block prints “This is the finally block” regardless of what happened in try or catch.

A few years ago, I went to an Atlanta Java Users Group meeting at which Venkat Subramanian talked about good practices in exception handling. One thing stuck out at that talk more than probably any other talk I’ve ever been to: if you’re going to have something fail with an exception, make sure the failure is as soon, as loud, and as clear as possible. That is, fail early, make it obvious that something failed, and, in the statement that something failed, be as detailed as you can. For example, you could always just use a RuntimeException, passing in no message to handle a problem, like our old friend division by zero. That technically works, but it would be much better if

  • The exception was triggered as early as possible, rather than delaying acknowledging the problem, or passing it down endlessly
  • You used a more descriptive exception, like an ArithmeticException, or perhaps even your own custom-written CannotDivideByZeroException
  • You passed a message into your exception to explain where, how, why, or all three, the code failed

No comments:

Post a Comment

Switch

 Other than if/if-else/if-else if-else and the ternary operator, there is yet another common and important conditional expression in Java th...