Introduction
Declaring exceptions means telling the compiler that a method might throw a checked exception. Use the throws keyword.
Why Declare?
For checked exceptions, you must either:
- Handle with try-catch, OR
- Declare with throws
If you don’t handle it, declare it so caller knows to handle.
throws Keyword
Syntax:
accessModifier returnType methodName() throws ExceptionType {
// Method body
}
Simple Example
import java.io.*;
class FileHandler {
// Declaring that this method may throw IOException
void readFile(String filename) throws IOException {
FileReader fr = new FileReader(filename); // May throw FileNotFoundException
BufferedReader br = new BufferedReader(fr);
String line = br.readLine(); // May throw IOException
System.out.println(line);
br.close();
}
}
public class Main {
public static void main(String[] args) {
FileHandler handler = new FileHandler();
// Must handle declared exception
try {
handler.readFile("test.txt");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Without Declaration (Error)
import java.io.*;
// ✗ Won't compile - must handle or declare
void readFile(String filename) {
FileReader fr = new FileReader(filename); // Compile error!
// Error: Unhandled exception java.io.FileNotFoundException
}
With Declaration (Correct)
import java.io.*;
// ✓ Compiles - exception declared
void readFile(String filename) throws FileNotFoundException {
FileReader fr = new FileReader(filename);
// Caller must handle this exception
}
Multiple Exceptions
Declare multiple exceptions separated by comma.
import java.io.*;
import java.sql.*;
class DataHandler {
// Method may throw multiple exceptions
void processData(String filename) throws IOException, SQLException {
// File operations - may throw IOException
FileReader fr = new FileReader(filename);
// Database operations - may throw SQLException
// Connection conn = DriverManager.getConnection(...);
}
}
public class Main {
public static void main(String[] args) {
DataHandler handler = new DataHandler();
// Handle both exceptions
try {
handler.processData("data.txt");
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
} catch (SQLException e) {
System.out.println("Database error: " + e.getMessage());
}
}
}
Exception Propagation
When method declares exception, caller must handle or declare again.
import java.io.*;
class Demo {
// Level 3 - throws exception
void method3() throws IOException {
FileReader fr = new FileReader("test.txt");
}
// Level 2 - declares same exception (propagates)
void method2() throws IOException {
method3(); // Declares exception, so we must too
}
// Level 1 - finally handles
void method1() {
try {
method2();
} catch (IOException e) {
System.out.println("Exception handled: " + e.getMessage());
}
}
}
public class Main {
public static void main(String[] args) {
Demo d = new Demo();
d.method1(); // No exception to handle here
}
}
Declaring in main()
Can declare in main() - JVM will handle.
import java.io.*;
public class Main {
// Declaring in main - JVM handles exception
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("test.txt");
BufferedReader br = new BufferedReader(fr);
System.out.println(br.readLine());
br.close();
}
}
Note: If exception occurs, program will terminate with error message.
Parent Exception
Can declare parent exception instead of specific.
import java.io.*;
// Specific exception
void method1() throws FileNotFoundException {
FileReader fr = new FileReader("test.txt");
}
// Parent exception (also valid)
void method2() throws IOException {
FileReader fr = new FileReader("test.txt"); // FileNotFoundException is subclass of IOException
}
// Most general
void method3() throws Exception {
FileReader fr = new FileReader("test.txt"); // Any exception
}
Best Practice: Declare specific exceptions for clarity.
Complete Example: Student Database
import java.io.*;
import java.sql.*;
class StudentDatabase {
// Method declares multiple exceptions
void loadFromFile(String filename) throws IOException {
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
// Method declares SQL exception
void saveToDatabase(String data) throws SQLException {
// Simulating database operation
if (data == null) {
throw new SQLException("Cannot save null data");
}
System.out.println("Saved to database: " + data);
}
// Method declares both exceptions
void importData(String filename) throws IOException, SQLException {
loadFromFile(filename); // May throw IOException
saveToDatabase("test data"); // May throw SQLException
}
}
public class Main {
public static void main(String[] args) {
StudentDatabase db = new StudentDatabase();
// Handle all declared exceptions
try {
db.loadFromFile("students.txt");
db.saveToDatabase("New Student");
db.importData("import.txt");
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("I/O error: " + e.getMessage());
} catch (SQLException e) {
System.out.println("Database error: " + e.getMessage());
}
}
}
Overriding Methods
Rules when overriding methods that declare exceptions:
Rule 1: Can declare same exception
class Parent {
void method() throws IOException { }
}
class Child extends Parent {
@Override
void method() throws IOException { } // ✓ OK - same
}
Rule 2: Can declare subclass exception
class Parent {
void method() throws IOException { }
}
class Child extends Parent {
@Override
void method() throws FileNotFoundException { } // ✓ OK - subclass
}
Rule 3: Cannot declare broader exception
class Parent {
void method() throws IOException { }
}
class Child extends Parent {
@Override
void method() throws Exception { } // ✗ Error - broader
}
Rule 4: Can declare no exception
class Parent {
void method() throws IOException { }
}
class Child extends Parent {
@Override
void method() { } // ✓ OK - no exception
}
Unchecked Exceptions
Don’t need to declare unchecked exceptions (but can).
// Unchecked - no need to declare
void divide(int a, int b) {
int result = a / b; // May throw ArithmeticException
System.out.println(result);
}
// Can declare if you want (but not required)
void divide2(int a, int b) throws ArithmeticException {
int result = a / b;
System.out.println(result);
}
Best Practice: Don’t declare unchecked exceptions (unnecessary).
Real-World Example: File Operations
import java.io.*;
class FileManager {
// Read file - declares IOException
String readFile(String filename) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(filename));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
content.append(line).append("\n");
}
br.close();
return content.toString();
}
// Write file - declares IOException
void writeFile(String filename, String content) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
bw.write(content);
bw.close();
}
// Copy file - declares IOException
void copyFile(String source, String dest) throws IOException {
String content = readFile(source); // May throw
writeFile(dest, content); // May throw
System.out.println("File copied successfully");
}
}
public class Main {
public static void main(String[] args) {
FileManager fm = new FileManager();
try {
String content = fm.readFile("input.txt");
System.out.println("File content:\n" + content);
fm.writeFile("output.txt", "Hello World");
System.out.println("File written");
fm.copyFile("source.txt", "destination.txt");
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("I/O error: " + e.getMessage());
}
}
}
throws vs throw
| Feature | throws | throw |
|---|---|---|
| Purpose | Declare exception | Throw exception |
| Usage | Method signature | Inside method body |
| Syntax | throws ExceptionType | throw new Exception() |
| Multiple | Yes (comma-separated) | No (one at a time) |
| Example | void m() throws IOException | throw new IOException() |
import java.io.*;
// throws - declares exception
void method1() throws IOException {
// May throw IOException
}
// throw - throws exception
void method2() {
throw new IOException("Error"); // Manually throw
}
// Both together
void method3() throws IOException {
if (someCondition) {
throw new IOException("Error occurred"); // throw inside
}
}
Best Practices
- Declare specific exceptions, not general Exception
- Document why exception may occur
- Don’t declare unchecked exceptions
- Order matters when catching (not declaring)
- Handle at appropriate level
- Don’t abuse throws in main()
Quick Reference
import java.io.*;
// Declare single exception
void method1() throws IOException {
FileReader fr = new FileReader("file.txt");
}
// Declare multiple exceptions
void method2() throws IOException, SQLException {
// Code that may throw either
}
// Propagate exception
void method3() throws IOException {
method1(); // Calls method that throws
}
// Handle exception (no declaration needed)
void method4() {
try {
method1();
} catch (IOException e) {
System.out.println("Handled");
}
}
// Declare in main
public static void main(String[] args) throws IOException {
method1(); // No need to handle
}
Common Mistakes
// ✗ Wrong - declaring unchecked (unnecessary)
void method1() throws NullPointerException {
String str = null;
str.length();
}
// ✗ Wrong - not handling or declaring checked
void method2() {
FileReader fr = new FileReader("file.txt"); // Compile error
}
// ✗ Wrong - broader exception in override
class Parent {
void method() throws IOException { }
}
class Child extends Parent {
void method() throws Exception { } // Error
}
// ✓ Correct - declare checked
void method3() throws IOException {
FileReader fr = new FileReader("file.txt");
}
// ✓ Correct - handle instead of declare
void method4() {
try {
FileReader fr = new FileReader("file.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
Exam Tips
Remember:
- throws keyword declares exceptions
- Checked exceptions must be declared or handled
- Multiple exceptions separated by comma
- Unchecked don’t need declaration
- Caller must handle declared exceptions
- Can declare in main() - JVM handles
- Override rules - same or narrower exception
- Parent exception can be declared
- throws vs throw - different purposes
- Best practice - declare specific exceptions
Common Questions:
- What is throws keyword?
- throws vs throw?
- How to declare multiple exceptions?
- Can we declare unchecked exceptions?
- What if method declares exception?
- Rules for overriding methods?
- Can we declare in main()?
- Purpose of declaring exceptions?
- What if we don’t declare checked exception?
- Can we declare parent exception?