Throw & Throws in Java
Learn how to signal and declare exceptions in your code
💡 Think of 'throw' like throwing a ball to someone - you actively toss it! And 'throws' is like warning 'Hey, I might throw a ball to you!' before you do it. One is the action, the other is the warning!
🎾 The throw Keyword
The 'throw' keyword is used to explicitly throw an exception. You create and throw an exception object when something goes wrong in your code.
public class ThrowExample { public static void main(String[] args) { // Example 1: Throwing an exception manually try { checkAge(15); } catch (IllegalArgumentException e) { System.out.println("Caught: " + e.getMessage()); } try { checkAge(25); } catch (IllegalArgumentException e) { System.out.println("Caught: " + e.getMessage()); } } public static void checkAge(int age) { System.out.println("\nChecking age: " + age); if (age < 18) { // Throwing an exception manually! throw new IllegalArgumentException( "Age must be 18 or older. Got: " + age ); } System.out.println("Age is valid!"); }}// Output:// Checking age: 15// Caught: Age must be 18 or older. Got: 15//// Checking age: 25// Age is valid!⚠️ The throws Keyword
The 'throws' keyword is used in method signatures to declare that a method might throw certain exceptions. It's a warning to anyone calling the method.
import java.io.IOException;public class ThrowsExample { public static void main(String[] args) { try { // We MUST handle the exception because readFile declares it readFile("data.txt"); } catch (IOException e) { System.out.println("Error: " + e.getMessage()); } } // The 'throws' keyword declares that this method might throw IOException public static void readFile(String filename) throws IOException { System.out.println("Reading file: " + filename); // Simulating a file read error if (filename.equals("data.txt")) { // We throw the exception here throw new IOException("File not found: " + filename); } System.out.println("File read successfully!"); }}// Output:// Reading file: data.txt// Error: File not found: data.txt// Note: The 'throws IOException' in the method signature warns callers// that they need to handle this exception!🔍 🔄 Key Differences
Understanding when to use throw vs throws:
throw
Used inside method body to actually throw an exception
throws
Used in method signature to declare possible exceptions
throw usage
throw new Exception('message')
throws usage
public void method() throws Exception
import java.io.IOException;public class ThrowVsThrows { public static void main(String[] args) { try { demonstrateThrowVsThrows(); } catch (IOException e) { System.out.println("Main caught: " + e.getMessage()); } } // 'throws' - declares exception in method signature public static void demonstrateThrowVsThrows() throws IOException { System.out.println("Inside method..."); // 'throw' - actually throws the exception throw new IOException("Something went wrong!"); // This line never executes // System.out.println("This won't print"); }}// Key difference:// - throws: Used in method declaration (warning)// - throw: Used inside method body (action)// Output:// Inside method...// Main caught: Something went wrong!🎂 Real-World Example: Age Validation
public class AgeValidator { public static void main(String[] args) { // Test different ages testRegistration("Alice", 25); testRegistration("Bob", 15); testRegistration("Charlie", -5); testRegistration("Diana", 200); } public static void testRegistration(String name, int age) { System.out.println("\n--- Registering: " + name + " ---"); try { validateAge(age); System.out.println("✓ Registration successful!"); } catch (IllegalArgumentException e) { System.out.println("✗ Registration failed: " + e.getMessage()); } } public static void validateAge(int age) { // Check for negative age if (age < 0) { throw new IllegalArgumentException( "Age cannot be negative! Got: " + age ); } // Check for too young if (age < 18) { throw new IllegalArgumentException( "Must be 18 or older. You are: " + age ); } // Check for unrealistic age if (age > 150) { throw new IllegalArgumentException( "Age seems unrealistic: " + age ); } System.out.println("Age " + age + " is valid"); }}// Output:// --- Registering: Alice ---// Age 25 is valid// ✓ Registration successful!//// --- Registering: Bob ---// ✗ Registration failed: Must be 18 or older. You are: 15//// --- Registering: Charlie ---// ✗ Registration failed: Age cannot be negative! Got: -5//// --- Registering: Diana ---// ✗ Registration failed: Age seems unrealistic: 200💰 Real-World Example: Bank Withdrawal
public class BankAccount { private String accountNumber; private double balance; public BankAccount(String accountNumber, double initialBalance) { this.accountNumber = accountNumber; this.balance = initialBalance; } // Method that throws exceptions for invalid operations public void withdraw(double amount) { System.out.println("\nAttempting to withdraw: $" + amount); // Validation: Check for negative amount if (amount < 0) { throw new IllegalArgumentException( "Withdrawal amount cannot be negative!" ); } // Validation: Check for zero amount if (amount == 0) { throw new IllegalArgumentException( "Withdrawal amount must be greater than zero!" ); } // Validation: Check for insufficient funds if (amount > balance) { throw new IllegalArgumentException( "Insufficient funds! Balance: $" + balance + ", Requested: $" + amount ); } // All validations passed - perform withdrawal balance -= amount; System.out.println("✓ Withdrawal successful!"); System.out.println("New balance: $" + balance); } public static void main(String[] args) { BankAccount account = new BankAccount("ACC123", 1000.0); System.out.println("Initial balance: $1000"); // Test valid withdrawal try { account.withdraw(200); } catch (IllegalArgumentException e) { System.out.println("Error: " + e.getMessage()); } // Test overdraft try { account.withdraw(2000); } catch (IllegalArgumentException e) { System.out.println("Error: " + e.getMessage()); } // Test negative amount try { account.withdraw(-50); } catch (IllegalArgumentException e) { System.out.println("Error: " + e.getMessage()); } }}// Output:// Initial balance: $1000//// Attempting to withdraw: $200.0// ✓ Withdrawal successful!// New balance: $800.0//// Attempting to withdraw: $2000.0// Error: Insufficient funds! Balance: $800.0, Requested: $2000.0//// Attempting to withdraw: $-50.0// Error: Withdrawal amount cannot be negative!📝 Declaring Multiple Exceptions
import java.io.IOException;import java.sql.SQLException;public class MultipleThrows { public static void main(String[] args) { try { processData("users.txt", "database_url"); } catch (IOException e) { System.out.println("File error: " + e.getMessage()); } catch (SQLException e) { System.out.println("Database error: " + e.getMessage()); } } // Method that can throw MULTIPLE exceptions // Separate them with commas! public static void processData(String filename, String dbUrl) throws IOException, SQLException { System.out.println("Processing data..."); // Simulate file reading if (filename.isEmpty()) { throw new IOException("Filename cannot be empty!"); } // Simulate database operation if (dbUrl.isEmpty()) { throw new SQLException("Database URL cannot be empty!"); } System.out.println("Data processed successfully!"); }}// Key points:// 1. Use 'throws' keyword followed by exception types// 2. Separate multiple exceptions with commas// 3. Caller must handle ALL declared exceptions// 4. Order doesn't matter for 'throws' (unlike catch blocks)🔄 Rethrowing Exceptions
public class RethrowingExceptions { public static void main(String[] args) { try { processUserInput("invalid"); } catch (IllegalArgumentException e) { System.out.println("Main caught: " + e.getMessage()); } } // This method catches, logs, and rethrows public static void processUserInput(String input) throws IllegalArgumentException { try { validateInput(input); } catch (IllegalArgumentException e) { // Log the error System.out.println("Logging error: " + e.getMessage()); // Do some cleanup System.out.println("Performing cleanup..."); // Rethrow the exception for caller to handle throw e; // Rethrowing the same exception } } public static void validateInput(String input) { if (input.equals("invalid")) { throw new IllegalArgumentException("Input validation failed!"); } }}// Output:// Logging error: Input validation failed!// Performing cleanup...// Main caught: Input validation failed!// Why rethrow?// - Log or record the error// - Perform cleanup operations// - Let higher-level code decide how to handle it// - Add context or wrap in different exception type✅ Real-World Example: Form Validation
public class FormValidator { public static void main(String[] args) { // Test valid form testForm("alice@email.com", "SecurePass123", 25); // Test invalid email testForm("invalid-email", "password123", 25); // Test weak password testForm("bob@email.com", "123", 25); // Test invalid age testForm("charlie@email.com", "SecurePass123", 10); } public static void testForm(String email, String password, int age) { System.out.println("\n=== Testing Form ==="); System.out.println("Email: " + email); System.out.println("Password: " + password); System.out.println("Age: " + age); try { validateEmail(email); validatePassword(password); validateAge(age); System.out.println("✓ Form validation passed!"); } catch (IllegalArgumentException e) { System.out.println("✗ Validation failed: " + e.getMessage()); } } public static void validateEmail(String email) { if (!email.contains("@")) { throw new IllegalArgumentException( "Email must contain @ symbol" ); } if (!email.contains(".")) { throw new IllegalArgumentException( "Email must contain a domain (.com, .org, etc.)" ); } } public static void validatePassword(String password) { if (password.length() < 8) { throw new IllegalArgumentException( "Password must be at least 8 characters long" ); } } public static void validateAge(int age) { if (age < 13) { throw new IllegalArgumentException( "Must be at least 13 years old" ); } }}// Output:// === Testing Form ===// Email: alice@email.com// Password: SecurePass123// Age: 25// ✓ Form validation passed!//// === Testing Form ===// Email: invalid-email// Password: password123// Age: 25// ✗ Validation failed: Email must contain @ symbol//// === Testing Form ===// Email: bob@email.com// Password: 123// Age: 25// ✗ Validation failed: Password must be at least 8 characters long//// === Testing Form ===// Email: charlie@email.com// Password: SecurePass123// Age: 10// ✗ Validation failed: Must be at least 13 years old🔑 Key Concepts
throw - Action
Actually creates and throws an exception
throw new IllegalArgumentException('Invalid input')
throws - Declaration
Declares that method might throw exceptions
public void read() throws IOException
Checked Exceptions
Must be declared with throws or caught
IOException, SQLException must use throws
Unchecked Exceptions
Don't need to be declared
RuntimeException, NullPointerException
✨ Best Practices
- ✓Use throw to signal errors when they occur
- ✓Declare exceptions with throws so callers know what to expect
- ✓Throw specific exception types, not generic Exception
- ✓Include meaningful error messages when throwing exceptions
- ✓Don't catch exceptions just to rethrow them without adding value
- ✓Document why your method throws each exception
💼 Interview Tips
- •Know the difference: throw is inside method, throws is in signature
- •Understand checked vs unchecked exceptions
- •Remember that throws declares multiple exceptions with commas
- •Know that RuntimeException and its subclasses don't need throws
- •Understand exception propagation up the call stack
- •Be able to explain when to throw vs when to handle exceptions