1. Java exceptions – quick repetition

In Java there are 3 types of errors which may be thrown and each of them extends the Java class Throwable.

  1. Error – those are coming from JVM and must not be used by developer. Error class is inherited by classes like: StackOverflowError, FatalError, AssertionError, NoClassDefFoundError, UnknownError and VirtualMachineError
  2. Checked exceptions – each checked exception should extend class Exception. Possibility of throwing such exception is known on the compilation step. When the method is marked with throws keyword then another method which will be using it has to handle exception from method signature, even if this class is not throwing it in the method body. Popular checked exceptions are: IOException, SQLException, InterruptedException, ReflectiveOperationException, AWTException
  3. Unchecked exceptions – those are the ones which are inheriting from the RuntimeException and therefore are called unchecked, that they don’t have to be handled even if the method has for example: throws IllegalArgumentException in its signature. Runtime exceptions are the best choice for input validation, or for some unwanted events like closed http connection, closed stream or blocked file.

Common interview question: throw vs throws
throw – makes the program to throw an exception, this keyword is used inside the code block, like method body. After the throw keyword is an object which should be thrown or rethrown.
Example: throw new Exception();
throws – used at the end of method signature, tells the compiler and programmer which exceptions might be thrown by the method and that they have to be handled by the code block which invokes it.
Example: public void erroneousMethod() throws IOException {};

2. Throwing error inside the finally block

What would happen if exception was thrown, by the try block, but finally will also throw another error?

Let’s see the code for our example:

void verifyCustomerName(String name) {
    if (name == null || name.equals("")) {
        throw new IllegalArgumentException("Customer name cannot be empty!");
    }
}

void processCustomer(String name) {
    try {
        verifyCustomerName(name);
    } catch(Exception e) {
        System.out.println("Customer name should not be empty!");
        throw e;
    } finally {
        System.out.println("Closing connection with the customer service");
        throw new RuntimeException("Closing connection failed");
    }
}

Method verifyCustomerName throws IllegalArgumentException which is catched inside catch block of the processCustomer method. Block finally throws also exception which is the RuntimeException. Which exception and what instructions will run? Let’s see what happens with our short test method:

@Test
void testProcessCustomer() {
    CustomerService customerService = new CustomerService();
    customerService.processCustomer("");
}

Do you know what will be the output in the console? And which exception will be thrown at the end? Try to guess and verify your knowledge with the result below:

Customer name should not be empty!
Closing connection with the customer service

java.lang.RuntimeException: Closing connection failed

Both blocks catch/finally were executed successfully from top to bottom. Block finally was executed just before throw e; would be executed. During execution of finally block there was thrown another error which is throw new RuntimeException("Closing connection failed"); – and this error hides the one which would be thrown inside the catch.

Many people are not aware of this behavior. You might get such interview question how exactly those exceptions are handled by Java Virtual Machine. Inside your production code also be aware if there is something in the finally block what can throw an error, if so then don’t rely on the exception thrown by the catch block. Think twice, and deliver bug-free code!