YouTip LogoYouTip

Java Exceptions

# Java Exception Handling In Java, exception handling is an important programming concept used to handle errors or exceptional situations that may occur during program execution. Exceptions are errors in a program, but not all errors are exceptions, and sometimes errors can be avoided. For example, if your code is missing a semicolon, the result will be an error `java.lang.Error`. If you use `System.out.println(11/0)`, you are using **0** as the divisor, which will throw an `java.lang.ArithmeticException` exception. There are many reasons for exceptions, usually including the following major categories: * The user entered illegal data. * The file to be opened does not exist. * The connection is interrupted during network communication, or JVM memory overflow. Some of these exceptions are caused by user errors, some by program errors, and others by physical errors. To understand how Java exception handling works, you need to master the following three types of exceptions: * **Checked Exceptions:** The most representative checked exceptions are those caused by user errors or problems. These exceptions are forced to be handled by the programmer at compile time. For example, when trying to open a file that does not exist, an exception occurs. These exceptions cannot simply be ignored at compile time. This type of exception is usually caught and handled using a try-catch block, or declared using a throws clause in the method declaration to indicate that the method may throw an exception. ```java try { // Code that might throw an exception } catch (IOException e) { // Code to handle the exception } ``` Or: ```java public void readFile() throws IOException { // Code that might throw IOException } ``` * **Runtime Exceptions:** These exceptions are not required to be handled at compile time and are usually caused by errors in the program, such as `NullPointerException`, `ArrayIndexOutOfBoundsException`, etc. Handling these exceptions is optional, not mandatory. ```java try { // Code that might throw an exception } catch (NullPointerException e) { // Code to handle the exception } ``` * **Errors:** Errors are not exceptions but problems beyond the programmer's control. Errors are usually ignored in code. For example, when a stack overflow occurs, an error occurs, and they cannot be checked at compile time. Java provides the following keywords and classes to support exception handling: * **try**: Used to wrap a block of code that might throw an exception. * **catch**: Used to catch and handle exceptions. * **finally**: Used to contain code that must be executed whether an exception occurs or not. * **throw**: Used to manually throw an exception. * **throws**: Used in a method declaration to specify the exceptions that the method may throw. * **Exception class**: The parent class of all exception classes. It provides some methods to get exception information, such as **getMessage()**, **printStackTrace()**, etc. --- ## Exception Class Hierarchy All exception classes are subclasses inherited from the `java.lang.Exception` class. The `Exception` class is a subclass of the `Throwable` class. Besides the `Exception` class, `Throwable` has another subclass called `Error`. Java programs usually do not catch errors. Errors generally occur during severe failures and are outside the scope of Java program handling. `Error` is used to indicate errors that occur in the runtime environment. For example, JVM memory overflow. Generally, programs do not recover from errors. Exception classes have two main subclasses: the `IOException` class and the `RuntimeException` class. !(#) In Java's built-in classes (which will be explained next), most of the commonly used checked and unchecked exceptions are included. --- ## Java Built-in Exception Classes The Java language defines some exception classes in the `java.lang` standard package. The subclasses of the standard runtime exception classes are the most common exception classes. Since the `java.lang` package is loaded by default in all Java programs, most exceptions inherited from the runtime exception class can be used directly. Java also defines other exceptions based on various class libraries. The following table lists Java's unchecked exceptions. | **Exception** | **Description** | | --- | --- | | `ArithmeticException` | Thrown when an exceptional arithmetic condition has occurred. For example, an integer "division by zero". | | `ArrayIndexOutOfBoundsException` | Thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array. | | `ArrayStoreException` | Thrown to indicate that an attempt has been made to store the wrong type of object into an array of objects. | | `ClassCastException` | Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. | | `IllegalArgumentException` | Thrown to indicate that a method has been passed an illegal or inappropriate argument. | | `IllegalMonitorStateException` | Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor, without owning the specified monitor. | | `IllegalStateException` | Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation. | | `IllegalThreadStateException` | Thrown to indicate that a thread is not in an appropriate state for the requested operation. | | `IndexOutOfBoundsException` | Thrown to indicate that an index of some sort (such as to an array, to a string, or to a vector) is out of range. | | `NegativeArraySizeException` | Thrown if an application tries to create an array with a negative size. | | `NullPointerException` | Thrown when an application attempts to use `null` in a case where an object is required. | | `NumberFormatException` | Thrown to indicate that the application has attempted to convert a string to one of the numeric types, but that the string does not have the appropriate format. | | `SecurityException` | Thrown by the security manager to indicate a security violation. | | `StringIndexOutOfBoundsException` | Thrown by `String` methods to indicate that an index is either negative or greater than the size of the string. | | `UnsupportedOperationException` | Thrown to indicate that the requested operation is not supported. | The following table lists the checked exception classes defined by Java in the `java.lang` package. | **Exception** | **Description** | | --- | --- | | `ClassNotFoundException` | Thrown when an application tries to load in a class through its string name using one of the methods for loading classes, but no definition for the class with the specified name could be found. | | `CloneNotSupportedException` | Thrown when a program tries to clone an object that does not implement the `Cloneable` interface. | | `IllegalAccessException` | Thrown when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor. | | `InstantiationException` | Thrown when an application tries to use the Java `Class` representation to obtain an object for a class that is abstract, an interface, an array class, a primitive type, or `void`; or if the class has no nullary constructor; or if the instantiation fails for some other reason. | | `InterruptedException` | Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. | | `NoSuchFieldException` | Thrown when a particular field cannot be found. | | `NoSuchMethodException` | Thrown when a particular method cannot be found. | --- ## Exception Methods The following is a list of the main methods of the `Throwable` class: | **No.** | **Method and Description** | | --- | --- | | 1 | **public String getMessage()** Returns the detailed message of the throwable that has occurred. This message is initialized in the Throwable constructor. | | 2 | **public Throwable getCause()** Returns a Throwable object representing the cause of the throwable. | | 3 | **public String toString()** Returns the short description of this Throwable. | | 4 | **public void printStackTrace()** Prints this Throwable and its backtrace to the standard error stream. | | 5 | **public StackTraceElement [] getStackTrace()** Returns an array of stack trace elements. The element at index 0 represents the top of the call stack, and the last element in the array represents the bottom of the call stack. | | 6 | **public Throwable fillInStackTrace()** Fills the stack trace of this Throwable object with the current stack trace, adding to any previous information in the stack trace. | --- ## Catching Exceptions Use the `try` and `catch` keywords to catch exceptions. The try/catch block is placed around the code where an exception might occur. The code in the try/catch block is called protected code, and the syntax for using try/catch is as follows: ```java try { // Program code } catch (ExceptionName e1) { // Catch block } The Catch statement contains the declaration of the exception type to be caught. When an exception occurs in the protected code block, the catch block following the try is checked. If the exception that occurred is included in the catch block, the exception is passed to the catch block, just like passing an argument to a method. ### Example In the following example, an array with two elements is declared. When the code tries to access the fourth element of the array, an exception is thrown. ## ExcepTest.java File Code: ```java import java.io.*; public class ExcepTest { public static void main(String args[]) { try { int a[] = new int; System.out.println("Access element three :" + a); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); } System.out.println("Out of the block"); } } The above code compiles and runs to produce the following output: Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 Out of the block --- ## Multiple Catch Blocks A situation where a try block is followed by multiple catch blocks is called multiple catch. The syntax for multiple catch blocks is as follows: ```java try { // ... } catch (ExceptionType1 e1) { // ... } catch (ExceptionType2 e2) { // ... } catch (ExceptionType3 e3) { // ... } The above code segment contains 3 catch blocks. You can add any number of catch blocks after a try statement. If an exception occurs in the protected code, the exception is thrown to the first catch block. If the data type of the thrown exception matches `ExceptionType1`, it is caught here. If it does not match, it is passed to the second catch block. This continues until the exception is caught or passes through all catch blocks. ### Example This example demonstrates how to use multiple try/catch. ```java try { file = new FileInputStream(fileName); x = (byte) file.read(); } catch (FileNotFoundException f) { f.printStackTrace(); return -1; } catch (IOException i) { i.printStackTrace(); return -1; } --- ## Multi-Catch Block (Merging Multiple Exceptions) Starting from Java 7, a more concise syntax was introduced β€” the multi-catch block, which allows a single catch block to handle multiple unrelated exceptions. ```java try { // Code that might throw multiple different types of exceptions } catch (ExceptionType1 | ExceptionType2 | ExceptionType3 e) { // Unified handling } **Note:** * `ExceptionType1`, `ExceptionType2`, etc., must not have an inheritance relationship, otherwise it will cause a compile-time error. * The exception variable name is a common reference variable for these three exceptions, so you cannot call their specific methods within the catch block. * The compiler will infer the type of this exception variable as the most specific common superclass of these exceptions (e.g., `Exception` or `IOException`). For example, if you might throw both `SQLException` and `IOException`, which are unrelated: ### Example ```java try { // Might throw both SQL and IO exceptions doSomething(); } catch (SQLException | IOException e) { System.out.println("SQL or IO exception occurred!"); e.printStackTrace(); } Incorrect example (cannot merge parent-child class exceptions): ```java // Incorrect! This will cause a compile error. catch (FileNotFoundException | IOException e) { // ... } `FileNotFoundException` is a subclass of `IOException`, so this syntax is actually invalid and will result in a compile error. --- ## throws/throw Keywords In Java, the `throw` and `throws` keywords are used for exception handling. The `throw` keyword is used to throw an exception in the code, while the `throws` keyword is used in a method declaration to specify the types of exceptions that may be thrown. ### throw Keyword The `throw` keyword is used to throw an exception within the current method. Typically, when code execution reaches a condition where it cannot continue normally, the `throw` keyword can be used to throw an exception to inform the caller of the current execution state. For example, in the code below, the method checks if `num` is less than 0. If so, it throws an `IllegalArgumentException` exception. ### Example ```java public void checkNumber(int num) { if (num " + line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } } } The output of the above example is: IOException in try block =>test.txt (No such file or directory) In the above example, we instantiate a `BufferedReader` object to read data from the `test.txt` file. The `BufferedReader` object is declared and instantiated in the `try-with-resources` statement. After execution, the resource is closed, without needing to consider whether the `try` statement executed normally or threw an exception. If an exception occurs, you can use `catch` to handle it. Now, let's look at using `finally` instead of **try-with-resources** to close the resource. The overall code volume increases significantly, and it becomes more complex and cumbersome: ### Example ```java import java.io.*; class TutorialTest { public static void main(String[] args) { BufferedReader br = null; String line; try { System.out.println("Entering try block"); br = new BufferedReader(new FileReader("test.txt")); while ((line = br.readLine()) != null) { System.out.println("Line =>" + line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } finally { System.out.println("Entering finally block"); try { if (br != null) { br.close(); } } catch (IOException e) { System.out.println("IOException in finally block =>" + e.getMessage()); } } } } The output of the above example is: Entering try block IOException in try block =>test.txt (No such file or directory) Entering finally block ### try-with-resources Handling Multiple Resources You can declare multiple resources in a `try-with-resources` statement by separating them with a semicolon `;`: ### Example ```java import java.io.*; import java.util.*; class TutorialTest { public static void main(String[] args) throws IOException { try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } } } } The above example uses a `Scanner` object to read a line from the `testRead.txt` file and write it to a new `testWrite.txt` file. When multiple resources are declared, the `try-with-resources` statement closes them in reverse order. In this example, the `PrintWriter` object is closed first, then the `Scanner` object. > For more information, refer to: > > * try-with-resources: (#) > * Resource Management: (#) --- ## Declaring Custom Exceptions In Java, you can define your own exceptions. When writing your own exception class, remember the following points. * All exceptions must be subclasses of `Throwable`. * If you want to write a checked exception class, you need to inherit from the `Exception` class. * If you want to write a runtime exception class, you need to inherit from the `RuntimeException` class. You can define your own exception class like this: ```java class MyException extends Exception { // ... } Creating an exception class by only inheriting from `Exception` results in a checked exception class. The following `InsufficientFundsException` class is a user-defined exception class that inherits from `Exception`. An exception class, like any other class, contains variables and methods. ### Example The following example is a simulation of a bank account, identified by the account number, allowing deposit and withdrawal operations. ## InsufficientFundsException.java File Code: ```java import java.io.*; public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } } To demonstrate how to use our custom exception class, the following `CheckingAccount` class contains a `withdraw()` method that throws an `InsufficientFundsException` exception. ## CheckingAccount.java File Code: ```java import java.io.*; public class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if (amount <= balance) { balance -= amount; } else { double needs = amount - balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } } The following `BankDemo` program demonstrates how to call the `deposit()` and `withdraw()` methods of the `CheckingAccount` class. ## BankDemo.java File Code: ```java public class BankDemo { public static void main(String[] args) { CheckingAccount c = new CheckingAccount(101); System.out.println("Depositing $500..."); c.deposit(500.00); try { System.out.println("nWithdrawing $100..."); c.withdraw(100.00); System.out.println("nWithdrawing $600..."); c.withdraw(600.00); } catch (InsufficientFundsException e) { System.out.println("Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } } Compile and run the above three classes, and the output is as follows: Depositing $500... Withdrawing $100... Withdrawing $600... Sorry, but you are short $100.0 java.lang.InsufficientFundsException: $100.0 at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13)
← Java BytearrayinputstreamJava Files Io β†’