Definition
throwis a statement inside the method body:throw new IllegalArgumentException("msg"). It creates an exception object and immediately raises it, stopping method execution.throwsis a declaration in the method signature:public void read() throws IOException. It tells the compiler and the caller which checked exceptions this method might produce.throwis followed by an exception object (throw new X()orthrow existingVariable).throwsis followed by exception class names (throws IOException, SQLException).throwworks with one exception per statement.throwscan list multiple exception types separated by commas.- For unchecked exceptions,
throwsis optional. For checked exceptions, eitherthrowsor try-catch is required.
At National Bank of India, throw is the teller actually pressing the alarm button: the alarm goes off right now. throws is the warning sign posted on the counter that reads "This counter may trigger a fraud alert." The sign warns customers (callers) that an alarm might happen. The button (throw) makes it happen. You need the sign (throws) for certain types of alarms (checked exceptions), but for others (unchecked) the sign is optional.
Understanding the Concepts
What is the throw keyword?
The throw keyword is a statement that creates an exception object and raises it immediately. Execution stops at the throw statement, and the exception propagates up the call stack until a matching catch block is found.
package com.bank.service;
import java.math.BigDecimal;
public class WithdrawalService {
private BigDecimal balance = new BigDecimal("50000.00");
public void withdraw(BigDecimal amount) {
if (amount == null) {
throw new IllegalArgumentException("Amount must not be null");
// Execution stops here. Lines below never run.
}
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Amount must be positive: " + amount);
}
if (amount.compareTo(balance) > 0) {
throw new IllegalStateException(
"Insufficient balance: requested Rs." + amount + ", available Rs." + balance);
}
balance = balance.subtract(amount);
System.out.println("Withdrawn Rs." + amount + ". Remaining: Rs." + balance);
}
public static void main(String[] args) {
WithdrawalService service = new WithdrawalService();
service.withdraw(new BigDecimal("10000.00"));
try {
service.withdraw(new BigDecimal("-500.00"));
} catch (IllegalArgumentException e) {
System.out.println("Caught: " + e.getMessage());
}
}
}
Withdrawn Rs.10000.00. Remaining: Rs.40000.00
Caught: Amount must be positive: -500.00
What is the throws keyword?
The throws keyword appears in the method signature after the parameter list. It declares which checked exceptions the method might produce. The compiler uses this information to force callers to handle those exceptions.
package com.bank.service;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class TradeFileReader {
// throws declares that this method might produce IOException
public String readFile(String filePath) throws IOException {
return Files.readString(Path.of(filePath));
}
// Multiple checked exceptions separated by commas
public String readAndParse(String filePath) throws IOException, ClassNotFoundException {
String content = readFile(filePath);
Class.forName("com.bank.parser.TradeParser");
return content;
}
public static void main(String[] args) {
TradeFileReader reader = new TradeFileReader();
try {
String data = reader.readFile("/trades/batch.csv");
System.out.println("Loaded: " + data.length() + " chars");
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
}
}
}
File error: /trades/batch.csv
How are throw and throws different?
| Feature | throw | throws |
|---|---|---|
| What it is | Statement (inside method body) | Declaration (in method signature) |
| Where it appears | Inside the method body | After method parameters, before body |
| Followed by | Exception object (new X()) | Exception class names |
| How many | One exception per statement | Multiple: throws A, B, C |
| Purpose | Actually raises the exception now | Warns callers about possible exceptions |
| Required for | Raising any exception | Checked exceptions only |
package com.bank.demo;
import java.io.IOException;
public class ThrowVsThrowsDemo {
// throws = DECLARATION in signature (class names, comma-separated)
public static void riskyOperation() throws IOException {
// throw = STATEMENT in body (exception object)
throw new IOException("Trade file corrupt");
}
public static void main(String[] args) {
try {
riskyOperation();
} catch (IOException e) {
System.out.println("throws declared it, throw raised it: " + e.getMessage());
}
}
}
throws declared it, throw raised it: Trade file corrupt
Do unchecked exceptions need a throws declaration?
No. Unchecked exceptions (subclasses of RuntimeException) do not require a throws declaration. You can add one for documentation purposes, but the compiler does not enforce it on callers.
package com.bank.demo;
import java.math.BigDecimal;
public class UncheckedThrowsDemo {
// No throws needed for unchecked exceptions
public static void validateAmount(BigDecimal amount) {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
}
// You CAN add throws for documentation, but it is optional
public static void validateAmountDocumented(BigDecimal amount)
throws IllegalArgumentException {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
}
public static void main(String[] args) {
// Both methods work the same way. The throws clause on the second
// method is purely for documentation. The compiler does not force
// the caller to catch IllegalArgumentException.
validateAmount(new BigDecimal("100"));
validateAmountDocumented(new BigDecimal("100"));
System.out.println("Both methods accept valid input identically");
}
}
Both methods accept valid input identically
How do throw and throws work together in real code?
In practice, you often use both in the same method. The throws clause declares the contract, and the throw statement fulfills it.
package com.bank.service;
import java.math.BigDecimal;
public class TransferService {
private BigDecimal balance = new BigDecimal("100000.00");
// throws DECLARES: this method might produce InsufficientFundsException
public String transfer(String fromAccount, String toAccount, BigDecimal amount)
throws InsufficientFundsException {
// throw RAISES: unchecked exception for invalid input
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("Transfer amount must be positive");
}
// throw RAISES: checked exception for business condition
if (amount.compareTo(balance) > 0) {
throw new InsufficientFundsException(balance, amount);
}
balance = balance.subtract(amount);
return "UTR" + System.currentTimeMillis();
}
public static void main(String[] args) {
TransferService service = new TransferService();
try {
String utr = service.transfer("SAV2001", "CUR3001", new BigDecimal("25000"));
System.out.println("Transfer successful. UTR: " + utr);
} catch (InsufficientFundsException e) {
System.out.println("Transfer failed: " + e.getMessage());
}
}
}
class InsufficientFundsException extends Exception {
public InsufficientFundsException(BigDecimal balance, BigDecimal requested) {
super("Balance Rs." + balance + " insufficient for Rs." + requested);
}
}
Transfer successful. UTR: UTR1703123456789
What are common mistakes with throw and throws?
package com.bank.demo;
import java.io.IOException;
public class ThrowMistakesDemo {
// WRONG: throw without throws for checked exception
// This does NOT compile:
// public static void wrong() {
// throw new IOException("missing throws!");
// // Compiler error: Unhandled exception: java.io.IOException
// }
// CORRECT: declare throws for checked exception
public static void correct() throws IOException {
throw new IOException("properly declared");
}
// WRONG: throwing null
// public static void throwNull() {
// throw null; // Compiles but throws NullPointerException at runtime!
// }
// WRONG: unreachable code after throw
// public static void unreachable() {
// throw new RuntimeException("error");
// System.out.println("never"); // Compiler error: unreachable statement
// }
public static void main(String[] args) {
try {
correct();
} catch (IOException e) {
System.out.println("Caught: " + e.getMessage());
}
// Demonstrating throw null
try {
throw (RuntimeException) null;
} catch (NullPointerException e) {
System.out.println("throw null causes NullPointerException");
}
}
}
Caught: properly declared
throw null causes NullPointerException
What about method overriding and throws?
When you override a method, the overriding method can declare fewer or narrower checked exceptions, but it cannot declare new or broader checked exceptions. This rule ensures that code using the parent type is not surprised by unexpected exceptions.
package com.bank.demo;
import java.io.FileNotFoundException;
import java.io.IOException;
public class OverrideThrowsDemo {
static class BaseService {
public void process() throws IOException {
System.out.println("Base processing");
}
}
// VALID: narrower exception (FileNotFoundException is-a IOException)
static class NarrowService extends BaseService {
@Override
public void process() throws FileNotFoundException {
System.out.println("Narrow processing");
}
}
// VALID: no exception at all (fewer than parent)
static class SafeService extends BaseService {
@Override
public void process() {
System.out.println("Safe processing, no exceptions");
}
}
// INVALID: broader exception would not compile
// static class BroadService extends BaseService {
// @Override
// public void process() throws Exception { // COMPILE ERROR
// System.out.println("Broad processing");
// }
// }
public static void main(String[] args) throws IOException {
BaseService narrow = new NarrowService();
narrow.process();
BaseService safe = new SafeService();
safe.process();
}
}
Narrow processing
Safe processing, no exceptions
What are common interview follow-up questions?
- Can you re-throw an exception? (Yes,
catch (Exception e) { throw e; }re-throws the same object.) - Can throw be used outside a method? (No, throw is a statement that must be inside a method, constructor, or initializer block.)
- Can throws appear on a constructor? (Yes, constructors can declare throws for checked exceptions.)
- What happens if you throw in a finally block? (It replaces any exception from the try block, which is dangerous.)
Visual Overview
Method Signature Method Body
───────────────────────── ─────────────────────────
public void transfer(...) {
throws IOException, if (bad input)
SQLException throw new IAE("msg");
─────────────────────────
│ if (business rule fails)
│ throws = DECLARATION throw new ISE("msg");
│ (class names)
│ (warns caller) if (IO fails)
│ (required for checked) throw new IOE("msg");
│ }
│ │
│ │ throw = STATEMENT
│ │ (exception object)
│ │ (raises immediately)
│ │ (stops execution)
▼ ▼
Key Takeaway
The throw keyword is a statement inside a method body that creates an exception object and raises it immediately. Execution stops at the throw statement, and the exception propagates up the call stack. The throws keyword is a declaration in the method signature that tells callers which checked exceptions the method might produce. The compiler forces callers to handle declared checked exceptions with try-catch or their own throws declaration.
In the transfer service at National Bank of India, Rajesh uses throw new IllegalArgumentException("Amount must be positive") for invalid input (unchecked, no throws needed) and throw new InsufficientFundsException(balance, amount) for business failures (checked, requires throws in the signature). The method signature declares throws InsufficientFundsException so the controller knows to catch it and return an appropriate HTTP response.
Key distinctions: throw is followed by an exception object, throws is followed by class names. throw raises one exception, throws can list multiple. For unchecked exceptions, throws is optional. For checked exceptions, either throws or try-catch is required. When overriding a method, you can narrow the throws clause but never broaden it.
Remember one sentence: throw creates and raises an exception right now, while throws warns the caller that an exception might happen.
---