Java Exceptions  «Prev  Next»

Lesson 4Exceptions and methods
ObjectiveHandle Possible Exceptions within Methods.

Handling Exceptions in Java 17: A Methodical Approach for Developers

In Java, exceptions represent unexpected events that may occur during the execution of a program. By version 17, Java has established a robust mechanism for handling exceptions to ensure the stability and predictability of applications. Let's delve into the methodologies Java developers employ to address exceptions within methods:
  1. Types of Exceptions: Before diving into handling mechanisms, it's essential to recognize the two primary categories of exceptions in Java:
    1. Checked Exceptions: These are exceptional conditions that a well-written application should anticipate and recover from. They are checked at compile-time, and the developer is compelled to handle them.
    2. Unchecked Exceptions: These encompass both runtime exceptions and errors. They are not checked at compile-time, and while they can be caught, they often indicate programming bugs or critical conditions.
  2. The `try-catch` Block: The primary mechanism to handle exceptions is the `try-catch` block.
    try {
       // Code that might generate an exception
    } catch (SpecificExceptionType e)  
       // Handle the specific exception
    } catch (AnotherExceptionType e) {
       // Handle another exception
    } finally {
       // Cleanup code that runs regardless of an exception occurring
    }
    
    1. Multiple `catch` Blocks: You can have multiple `catch` blocks to handle different exception types distinctly. The JVM catches the first matching exception type.
    2. The `finally` Block: This block is optional and, if present, always executes—irrespective of whether an exception was thrown or not. It's commonly used for cleanup operations.
  3. The `throws` Clause: If a method cannot handle an exception itself (or chooses not to), it can propagate the exception to its caller using the `throws` keyword in its declaration.
    public void sampleMethod() throws SpecificExceptionType {
       // Method implementation
    }
    

    For checked exceptions, if they're not caught within the method, they must be declared using the `throws` clause. Unchecked exceptions are exempted from this obligation.
  4. The `throw` Keyword: To manually throw an exception, either a built-in Java exception or a custom exception, where the developer can use the `throw` keyword.
    if (someCondition) {
       throw new SpecificExceptionType("Descriptive error message");
    }
    


  5. Advancements in Java 17: By Java 17, there haven't been foundational changes to the exception handling mechanism itself. However, developers have continued benefits from improved standard library exception classes, enhanced diagnostic messages, and other refinements introduced in preceding versions.
  6. Best Practices:
    1. Meaningful Messages: Always provide comprehensive, informative messages when throwing exceptions to aid debugging.
    2. Avoid Catching `Exception` Directly: Catching the base `Exception` class can unintentionally trap unrelated exceptions. It's more precise to catch specific exception types.
    3. Utilize Finally for Cleanup: Use the `finally` block for resource deallocation or other cleanup operations to ensure they always execute.
    4. Document with `@throws`: When a method uses the `throws` clause, it's beneficial to document the potential exception using the `@throws` (or `@exception`) Javadoc tag.

Exception handling remains a critical aspect of Java development, ensuring the resilience and robustness of applications. Through mechanisms like `try-catch`, `throws`, and the careful design of exception hierarchies, Java 17 equips developers with the tools to tackle unexpected events methodically and maintain application integrity.

If a method contains code that is capable of throwing an exception, it must indicate as such in its declaration with a throws clause:
public void readFile() throws FileNotFoundException {
  FileInputStream in = 
    new FileInputStream("Diary.txt");
  // read the file from the stream…
}

In this example, the FileInputStream constructor is capable of throwing a FileNotFoundException if the file Diary.txt is not found. This exception is thrown from the method sort of like a return value, and the code calling the method must handle the exception or continue passing it up the call stack. You can also handle the exception directly in the method and forgo using the throws clause in the method declaration.
You will learn how this is done in the next lesson.


CheckedException Example

Listing 5-4 CheckedExceptionExample3.java
import java.io.*;
class CheckedExceptionExample3 {
 public static void main(String []args) {
  try {
   FileInputStream fis = new FileInputStream(args[0]);
  } 
  catch(FileNotFoundException fnfe) {
   System.out.println("Error: There is no file that exists with name "
   + args[0]);
  System.out.println("Pass a valid file name as commandline argument!");
  }
 }
}

Now, when passed with a name of the file that does not exist, the program will terminate and show this useful error message to the user:
D:\ > java CheckedExceptionExample3 somefile.txt
Error: There is no file that exists with name somefile.txt
Pass a valid file name as commandline argument!

Note: If you have some code that can throw a checked exception from a method, you can choose between the two alternatives. You can either handle that exception by providing a catch block or declare that method to throw that exception. If you don’t catch or declare the method to throw that exception, your code won’t compile.
What will be the output of trying to compile and run the following piece of code?
public class Mango {
 public static void main(String [] args) throws Exception {
  try {
   try {
     throw new RuntimeException("Run time Exception");
   } catch (Exception e) {
   throw new Exception("Exception", e);
  }
 } catch (Exception e) {
   System.out.println(e.getCause().getMessage());
  }
 }
}


  1. Compilation fails
  2. Compilation Succeeds but java.lang.Exception is thrown at runtime
  3. Compilation Succeeds but java.lang.RuntimeException is thrown at runtime
  4. Compilation succeeds and prints RuntimeException at runtime
  5. Compilation succeeds and prints Exception at runtime

Answer: D
Explanation:
Correct answer is option D. The constructor within the inner catch block for java.lang.Exception takes two arguments:
  1. a string message and
  2. a throwable cause.
Here, the Run time Exception thrown from the previous block is set as a cause. Hence, in the other catch block, e.get Cause() returns this Run time Exception and calling get Message on it will print Run time Exception. As all exceptions are handled here, no exception will be thrown back to the console.

Exception Basics - Quiz

Click the Quiz link below to test your knowledge of exceptions.
Exception Basics - Quiz