Exception is an unwanted or unexpected event, which occurs during the execution of a program, (i.e. at run time, that disrupts the normal flow of the program’s instructions). Exceptions can be caught and handled by the program.

In Java, when an exception occurs within a method, it creates a Throwable object, the Throwable class is the superclass of all errors and exceptions in the Java language. This object is called an exception object, it contains information about the exception, such as the name and description of the exception and the state of the program when the exception occurred (e.g. cause, detailMessage, and stackTrace). Every time an exception occurs in a method, we say that the method throws an exception.

More about Throwable and Exception classes in Exception Hierarchy.

Types of exceptions

Checked exception

Checked exceptions are also known as compile-time exceptions because these exceptions are checked by the compiler during the compilation process. If a method can throw a checked exception, it must either handle it with a try-catch block or declare it using the throws keyword. The compiler enforces this rule, and if it’s not followed, a compilation error will occur. In many IDEs, the source where the exception can occur will be highlighted (often with a red squiggly underline) to notify the programmer before the actual compilation error is shown. Any class that is a subclass of Throwable, except those that are also subclasses of RuntimeException or Error is considered a checked exception. (learn more in Exception Hierarchy)

Unchecked exception

Unchecked exceptions, AKA runtime exceptions, are not checked by the compiler at compile-time, these include programming bugs, logic errors, or improper use of an API. Examples of unchecked exceptions include NullPointerException and ArrayIndexOutOfBoundsException. Unchecked exceptions include RuntimeException and its subclasses, as well as Error and its subclasses.

Error

Errors refer to issues that are external to the application and are often caused by a shortage of system resources. They are usually more serious than exceptions and application is not expected to handle them as they are outside the control of the program. Examples include StackOverflowError and LinkageError (error from JVM class loader sub-system).

Exception handling

Exception Handling in Java is one of the effective means to handle the runtime errors so that the regular flow of the application can be preserved. Whenever an exception occurs the Java runtime looks for a block of code in that method for handling the exception.

This is an error message output in the terminal when running a Java program, the stack trace information is printed.

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

This program throws a NullPointerException, the NullPointerException is a class declared in the package java.lang.

  • When an exception is thrown, the Java runtime attempts to find exception handler through stack trace (back trace) before the program aborted
  • If the stack is exhausted and no exception handler is found, the program terminates with exit code 1 and the stack trace information will be displayed in the terminal

Exception handling approach

In Java you handle exceptions using the following approaches:

  • Try-catch block
  • Finally block
  • Throws keyword
  • Custom exception handling by creating your own exception class

Try-catch block

Place the code that throw an exception inside the try block, the catch block is used to handle the exception. If there is an exception found, the runtime will pass the control to the corresponding catch block for handling that type of exception; every try block is followed by a catch block. In the catch parenthesis we specify the type of exception to catch follow by a name of the exception object normally e or ex (short for exception), the catch block catches the exception and statement inside the catch block is executed. Inside catch block we can print the exception message (getMessage()) or perform other operations using methods from the specific exception class or methods inherited from theThrowable class. Below is the exception handling using try-catch block for uncheck exception.

public static void main(String[] args) {
	try {
		int result = divide(10, 0);
		System.out.println("Result: " + result);
	} catch (ArithmeticException e) {
		System.err.println("Cannot divide by zero: " + e.getMessage());
	}
	
	public static int divide(int a, int b) {
		return a / b; // Can throw ArithmeticException
	}
}

Catch multiple exceptions Use pipes or multiple catch clauses to catch multiple exceptions.

public static void show() {
	try {  
	    var reader = new FileReader("text_file.txt");  
	    var value = reader.read();  
	    new SimpleDateFormat().parse("");  
	} catch (IOException | ParseException exception) {  
	    System.err.println("Cannot read data");  
	}
}

Reference: