In Java, the throw keyword is used to explicitly throw an exception.
It’s a powerful feature for handling error cases in your programs. You can throw either checked or unchecked exceptions, depending on your needs.
Syntax
The syntax for throw is as follows:
throw new ExceptionType("Error message");
When throw is used, it immediately terminates the execution of the method and passes control to the nearest enclosing try-catch block or, if not caught, propagates the exception up the call stack.
1. Throwing an Unchecked Exception (RuntimeException)
An unchecked exception, or runtime exception, doesn’t need to be declared in the throws clause of the method. These exceptions are subclasses of RuntimeException.
Example: Throwing IllegalArgumentException
This example throws an IllegalArgumentException if the provided age is negative.
public class ThrowUncheckedExceptionExample { public static void checkAge(int age) { if (age < 0) { throw new IllegalArgumentException("Age cannot be negative"); } else { System.out.println("Age is valid: " + age); } } public static void main(String[] args) { checkAge(25); // Valid case checkAge(-5); // Invalid case, throws exception } }
Explanation
- checkAge throws IllegalArgumentException if the age parameter is negative.
- Since IllegalArgumentException is an unchecked exception, we don’t need to handle it or declare it in the method signature.
- When checkAge(-5) is called, it throws the exception, stopping the method’s execution.
2. Throwing a Checked Exception (Exception)
Checked exceptions must either be caught or declared in the method signature using throws.
Common checked exceptions include IOException, SQLException, and Exception.
Example: Throwing IOException
This example demonstrates throwing an IOException when a file is not found.
import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class ThrowCheckedExceptionExample { public static void readFile(String filename) throws IOException { File file = new File(filename); if (!file.exists()) { throw new IOException("File not found: " + filename); } // Simulate reading the file System.out.println("Reading file: " + filename); } public static void main(String[] args) { try { readFile("test.txt"); // Throws exception if file doesn't exist } catch (IOException e) { System.out.println("Caught exception: " + e.getMessage()); } } }
Explanation
- readFile throws an IOException if the specified file does not exist.
- IOException is a checked exception, so readFile must declare it in its throws clause.
- The main method catches and handles the exception, printing a message to the console.
3. Throwing a Custom Exception
You can create custom exceptions by extending the Exception or RuntimeException classes.
Custom exceptions are helpful when you want to handle application-specific errors.
Example: Creating and Throwing a Custom Exception
This example defines a custom exception InvalidScoreException and throws it if a score is out of a valid range.
class InvalidScoreException extends Exception { public InvalidScoreException(String message) { super(message); } } public class ThrowCustomExceptionExample { public static void validateScore(int score) throws InvalidScoreException { if (score < 0 || score > 100) { throw new InvalidScoreException("Score must be between 0 and 100."); } else { System.out.println("Score is valid: " + score); } } public static void main(String[] args) { try { validateScore(85); // Valid score validateScore(110); // Invalid score, throws exception } catch (InvalidScoreException e) { System.out.println("Caught exception: " + e.getMessage()); } } }
Explanation
- InvalidScoreException extends Exception, making it a checked exception.
- validateScore throws an InvalidScoreException if the score is not between 0 and 100.
- In main, validateScore(110) throws an exception, which is caught and handled.
4. Throwing Exceptions in a Method and Propagating to the Caller
Exceptions can be thrown in one method and then propagated up the call stack to the calling method if not handled.
This approach allows centralized exception handling in the calling method.
Example: Propagating an Exception
In this example, an exception thrown in processFile propagates to main.
import java.io.IOException; public class ExceptionPropagationExample { public static void processFile(String filename) throws IOException { if (filename == null) { throw new IOException("Filename cannot be null"); } System.out.println("Processing file: " + filename); } public static void processRequest(String filename) throws IOException { processFile(filename); } public static void main(String[] args) { try { processRequest(null); } catch (IOException e) { System.out.println("Caught exception: " + e.getMessage()); } } }
Explanation
- processFile throws an IOException if the filename is null.
- processRequest calls processFile and doesn’t handle the exception, so it propagates to main.
- main catches the exception and handles it, centralizing error handling.
5. Using throw with try-catch-finally
The finally block is executed even if an exception is thrown.
This example demonstrates how to clean up resources after an exception is thrown.
public class ThrowWithFinallyExample { public static void divide(int numerator, int denominator) { try { if (denominator == 0) { throw new ArithmeticException("Cannot divide by zero"); } System.out.println("Result: " + (numerator / denominator)); } catch (ArithmeticException e) { System.out.println("Caught exception: " + e.getMessage()); } finally { System.out.println("Cleaning up resources."); } } public static void main(String[] args) { divide(10, 2); // Valid division divide(10, 0); // Throws exception } }
Explanation
- If denominator is 0, ArithmeticException is thrown, and it’s caught in the catch block.
- The finally block executes whether an exception is thrown or not, ensuring cleanup.
6. Throwing Exceptions in Constructors
You can use throw in constructors to validate parameters when creating an object.
This is useful to prevent invalid object creation.
Example: Throwing an Exception in a Constructor
In this example, a constructor throws an exception if an invalid parameter is passed.
class Employee { private String name; public Employee(String name) { if (name == null || name.isEmpty()) { throw new IllegalArgumentException("Name cannot be null or empty"); } this.name = name; } public String getName() { return name; } } public class ConstructorExceptionExample { public static void main(String[] args) { try { Employee emp = new Employee(""); // Throws exception } catch (IllegalArgumentException e) { System.out.println("Caught exception: " + e.getMessage()); } Employee emp2 = new Employee("Alice"); System.out.println("Employee name: " + emp2.getName()); } }
Explanation
- Employee constructor throws IllegalArgumentException if name is null or empty.
- This ensures that an invalid Employee object can’t be created.
- main catches and handles the exception.
7. Using throw with Multiple Exception Types
In Java, you can throw multiple types of exceptions based on different conditions within a single method.
Example: Throwing Multiple Exception Types
public class MultipleExceptionExample { public static void checkValue(int value) throws IllegalArgumentException, ArithmeticException { if (value < 0) { throw new IllegalArgumentException("Value cannot be negative"); } else if (value == 0) { throw new ArithmeticException("Value cannot be zero"); } else { System.out.println("Valid value: " + value); } } public static void main(String[] args) { try { checkValue(-1); } catch (IllegalArgumentException | ArithmeticException e) { System.out.println("Caught exception: " + e.getMessage()); } } }
Explanation
- checkValue can throw either IllegalArgumentException if value is negative or ArithmeticException if value is zero.
- In main, both exceptions are caught using a multi-catch block (catch (IllegalArgumentException | ArithmeticException e)).
Summary
The throw keyword in Java is used to create custom error-handling logic by explicitly throwing exceptions.
Key points include:
- Unchecked Exceptions: Do not require throws in method signature and are often used for programmer errors (e.g., IllegalArgumentException).
- Checked Exceptions: Must be declared in the method’s throws clause and are often used for recoverable errors (e.g
., IOException).
- Custom Exceptions: Useful for application-specific error handling.
- throw with try-catch-finally: Ensures resource cleanup.
- Constructors and Methods: Constructors can throw exceptions to prevent invalid objects from being created.
Using throw effectively improves code robustness and provides clear error messaging.