Exception Handling in Java: Detailed Notes, Examples & Practice Questions (Object Oriented Programming)

Hello dear students! Today we are going to study a very important chapter called Exception Handling. Have you ever written a program that was running fine and then suddenly stopped with some red error messages? That usually means an exception happened. In this lesson, I will teach you how to handle those errors gracefully so your program does not crash. This topic carries good marks in your exam, so please study each section carefully.

What is an Exception?

Let me start with a simple question. What do you think happens when you try to divide a number by zero in Java? Or what happens when you try to access an array element at index 10 when the array only has 5 elements? The program suddenly stops running and shows an error message. That error is called an exception.

An exception is an unwanted or unexpected event that happens during the execution of a program. It disrupts the normal flow of the program instructions. When an exception occurs, Java creates an exception object that contains information about the error, like the error name, the message, and the line number where it happened. This object is then “thrown” and the program looks for someone to “catch” it.

Let me show you what happens without exception handling:

public class Main { public static void main(String[] args) { int a = 10; int b = 0; int result = a / b; // This line causes an exception System.out.println(“Result: ” + result); // This line NEVER runs System.out.println(“Program ended normally”); // This line NEVER runs } }

Output:

Exception in thread “main” java.lang.ArithmeticException: / by zero at Main.main(Main.java:4)

See what happened? The program crashed at line 4 and the lines after it never executed. The error message tells us the exception name is ArithmeticException and the reason is “/ by zero”. This is a problem because in a real application, we do not want the entire program to crash just because of one bad division. We want to handle the error, show a friendly message to the user, and let the rest of the program continue. That is exactly what exception handling does for us.

Important Notes to Remember for Exam:
1. An exception is an abnormal event that disrupts the normal flow of program execution.
2. When an exception occurs, Java creates an exception object that contains error details.
3. Without exception handling, the program crashes at the line where the exception occurs.
4. Lines of code after the exception line do not execute.
5. Exception handling allows the program to recover from the error and continue running.
MCQ

Question 1: What happens when an exception occurs in a Java program and is not handled?

A) The program skips the bad line and continues    B) The program prints a warning and continues    C) The program terminates abruptly    D) The program restarts automatically

Answer: C) The program terminates abruptly

When an exception occurs and there is no code to handle it, the Java runtime system catches it and prints the error message along with the stack trace showing where the exception happened. Then it immediately terminates the program. None of the code after the exception line gets a chance to run. This is why we need exception handling, to prevent this sudden termination and allow the program to recover gracefully.

Fill in the Blank

Question 2: When an exception occurs in Java, an ________ object is created that contains information about the error.

Answer: exception

Java creates an exception object (an instance of a subclass of Throwable) that contains important information about the error: the name of the exception, a descriptive message, and the stack trace showing which methods were called and on which line the exception occurred. This object is then thrown up through the call stack until it is caught by an appropriate handler.

Types of Errors in Java

Before we go deep into exceptions, let me clarify the different types of errors you can encounter in Java. Students often confuse these in exams, so pay close attention.

1. Compile-Time Errors (Syntax Errors)

These errors are detected by the Java compiler before the program runs. They happen when you write code that does not follow Java syntax rules. For example, missing a semicolon, using a variable without declaring it, mismatched brackets, or misspelling a keyword.

int a = 10 // Missing semicolon – compile-time error if (a > 5 // Missing closing parenthesis – compile-time error System.out.println(“Hello”) // Missing semicolon – compile-time error

These errors must be fixed before the program can run at all. The compiler will not produce a .class file if there are compile-time errors.

2. Runtime Errors (Exceptions)

These errors happen while the program is running. The program compiles fine (no syntax errors), but something goes wrong during execution. For example, dividing by zero, accessing an invalid array index, or trying to access a null object. These are the errors that exception handling deals with.

// This compiles fine but crashes at runtime int[] arr = {1, 2, 3}; System.out.println(arr[10]); // ArrayIndexOutOfBoundsException at runtime

3. Logical Errors

These errors happen when the program compiles and runs without crashing, but produces wrong results. The logic of your code is incorrect. For example, using a plus sign instead of a minus sign in a calculation. Java cannot detect these for you. You must find them yourself through testing.

// This compiles and runs, but gives wrong result int area = length + width; // Should be length * width for rectangle area
Important Notes to Remember for Exam:
1. Compile-time errors are caught by the compiler before running. They are syntax errors.
2. Runtime errors happen during execution. They are the exceptions we handle using try-catch.
3. Logical errors produce wrong results but do not crash the program. Java cannot detect them.
4. Exception handling deals ONLY with runtime errors, not compile-time or logical errors.
5. A common exam question is to identify which type of error a given code has.
MCQ

Question 3: Which type of error can be handled using exception handling in Java?

A) Missing semicolon    B) Dividing an integer by zero    C) Using + instead of * for multiplication    D) Undefined variable name

Answer: B) Dividing an integer by zero

Option A is a compile-time error (missing semicolon). Option C is a logical error (wrong operator, but the program runs). Option D is a compile-time error (undefined variable). Only option B is a runtime error that causes an ArithmeticException at runtime, which can be handled using try-catch blocks. Exception handling in Java is designed specifically to deal with runtime errors.

Identify Error Type

Question 4: Identify the type of error in the following code: int result = 10 / 0;

Answer: Runtime Error (Exception)

The code int result = 10 / 0; has no syntax errors, so it compiles successfully. The error only happens when the program tries to execute the division by zero. At that point, Java throws an ArithmeticException. Since this error occurs during program execution (not at compile time), it is classified as a runtime error, and it can be handled using exception handling mechanisms like try-catch.

Exception Hierarchy in Java

Now let me explain the exception hierarchy because examiners love to ask about this. All exceptions and errors in Java are organized in a class hierarchy. At the very top is a class called Throwable. Everything that can be thrown in Java is a subclass of Throwable.

Throwable / \ / \ v v Error Exception / | \ / \ / | \ / \ v v v v v OutOfMemory StackOverflow RuntimeException IOException Error Error / | \ / \ / | \ / \ v v v v v Arithmetic NullPointer ArrayIndex FileNotFoundException Exception Exception OutOfBounds SQLException Exception Left side = Errors (should NOT be handled) Right side top = Checked Exceptions (must be handled) Right side bottom = Unchecked Exceptions (may or may not be handled)

Let me explain the main branches:

Error: Errors are serious problems that a program usually cannot recover from. Examples include OutOfMemoryError (when the JVM runs out of memory) and StackOverflowError (when a method calls itself too many times, creating infinite recursion). We do NOT try to handle errors using try-catch. They indicate problems with the system itself, not with our code logic.

Exception: Exceptions are problems that a program can potentially recover from. Exceptions are further divided into two categories:

  • Checked Exceptions: These are exceptions that the compiler forces you to handle. If your code might throw a checked exception, you MUST either catch it with try-catch or declare it with throws. Otherwise, the program will not compile. Examples: IOException, FileNotFoundException, SQLException. They are called “checked” because the compiler checks for them at compile time.
  • Unchecked Exceptions: These are exceptions that the compiler does NOT force you to handle. They occur due to programming mistakes (like dividing by zero or accessing a null object). The compiler will not complain if you do not handle them. All subclasses of RuntimeException are unchecked. Examples: ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException.
Important Notes to Remember for Exam:
1. The top of the hierarchy is Throwable. Both Error and Exception are its subclasses.
2. Errors should NOT be handled (system-level problems).
3. Checked exceptions MUST be handled or declared. The compiler enforces this.
4. Unchecked exceptions (subclasses of RuntimeException) do NOT need to be handled or declared.
5. Common checked exceptions: IOException, FileNotFoundException, SQLException.
6. Common unchecked exceptions: ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException, ClassCastException.
7. A very common exam question: “Which of the following is a checked exception?” Memorize the examples!
MCQ

Question 5: Which of the following is a checked exception?

A) ArithmeticException    B) NullPointerException    C) IOException    D) ArrayIndexOutOfBoundsException

Answer: C) IOException

IOException is a checked exception because it is a subclass of Exception but NOT a subclass of RuntimeException. The compiler requires you to handle or declare it. All the other options (ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException) are subclasses of RuntimeException, which makes them unchecked exceptions that the compiler does not force you to handle.

MCQ

Question 6: Which of the following is an unchecked exception?

A) FileNotFoundException    B) SQLException    C) ClassNotFoundException    D) NumberFormatException

Answer: D) NumberFormatException

NumberFormatException is a subclass of IllegalArgumentException, which is a subclass of RuntimeException. Since it inherits from RuntimeException, it is an unchecked exception. Options A, B, and C are all checked exceptions because they are subclasses of Exception but not of RuntimeException. The trick is to check whether the exception extends RuntimeException or not.

True or False

Question 7: The Java compiler forces you to handle or declare unchecked exceptions.

Answer: False

Only checked exceptions are enforced by the compiler. Unchecked exceptions (subclasses of RuntimeException) are not checked at compile time. You can choose to handle them or not, and the compiler will not complain either way. This is because unchecked exceptions typically represent programming mistakes that should be fixed in the code itself, rather than being handled at runtime.

The try-catch Block

Now let me teach you the most fundamental way to handle exceptions in Java: the try-catch block. This is the core of exception handling and you will use it in almost every program.

The idea is simple: you put the code that might cause an exception inside a try block, and you put the code that handles the exception inside a catch block. If an exception occurs in the try block, Java immediately stops executing the rest of the try block, jumps to the catch block, and executes the catch block code. If no exception occurs, the catch block is skipped entirely.

try block catch block +————————+ +————————+ | Line 1 (runs) | | | | Line 2 (runs) | | If exception occurred | | Line 3 (EXCEPTION!) —|—>| in try, this runs | | Line 4 (skipped) | | Error handling code | | Line 5 (skipped) | | | +————————+ +————————+ | v +————————+ | Rest of program | | (continues normally) | +————————+

Syntax:

try { // Code that might throw an exception } catch (ExceptionType variableName) { // Code that handles the exception } // Rest of the program continues normally

Let me rewrite our earlier division example with proper exception handling:

public class Main { public static void main(String[] args) { int a = 10; int b = 0; try { int result = a / b; // This might cause ArithmeticException System.out.println(“Result: ” + result); } catch (ArithmeticException e) { System.out.println(“Error: Cannot divide by zero!”); System.out.println(“Exception message: ” + e.getMessage()); } // This line NOW runs because the exception was handled System.out.println(“Program ended normally.”); } }

Output:

Error: Cannot divide by zero! Exception message: / by zero Program ended normally.

Do you see the difference? Earlier, the program crashed and the last line never ran. Now, the exception is caught in the catch block, a friendly error message is printed, and then the program continues to the next line and prints “Program ended normally.” This is the whole point of exception handling: catching the error so the program does not crash.

Let me explain the catch block parameters. ArithmeticException is the type of exception we are catching. The variable e is the exception object that Java created. Through this object, we can get information about the error. Some useful methods of the exception object are:

  • e.getMessage() – Returns a string describing the error
  • e.toString() – Returns the exception name plus the message
  • e.printStackTrace() – Prints the full stack trace (exception name, message, and line numbers)
try { int[] arr = new int[3]; arr[10] = 5; } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); // Index 10 out of bounds for length 3 System.out.println(e.toString()); // ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3 e.printStackTrace(); // Prints full details with line numbers }
Important Notes to Remember for Exam:
1. The try block contains code that might throw an exception.
2. The catch block contains code that handles the exception.
3. If an exception occurs in try, the remaining lines in try are skipped and control jumps to catch.
4. If no exception occurs, the catch block is completely skipped.
5. After try-catch, the program continues normally with the next statement.
6. A try block must be followed by at least one catch block or a finally block.
7. You cannot write a catch block without a try block.
8. The exception object e has methods: getMessage(), toString(), printStackTrace().
MCQ
See also  Inheritance and Polymorphism in Java: Detailed Notes, Examples & Practice Questions (Object Oriented Programming)

Question 8: What happens to the statements in a try block that come AFTER the line where an exception occurs?

A) They execute normally    B) They are skipped and control jumps to the catch block    C) They execute after the catch block finishes    D) They are moved to the finally block

Answer: B) They are skipped and control jumps to the catch block

When an exception occurs at a specific line inside the try block, Java immediately stops executing any remaining lines in that try block. Control jumps directly to the matching catch block. The skipped lines in the try block are NOT executed later, they are simply abandoned. This is important to remember for questions that ask about which lines execute and which do not.

Find the Output

Question 9: What will be the output of the following code?

public class Test { public static void main(String[] args) { System.out.println(“Line 1”); try { System.out.println(“Line 2”); int x = 10 / 0; System.out.println(“Line 3”); } catch (ArithmeticException e) { System.out.println(“Line 4”); } System.out.println(“Line 5”); } }

Output:

Line 1 Line 2 Line 4 Line 5

Explanation: “Line 1” prints normally before the try block. Inside try, “Line 2” prints. Then 10 / 0 throws an ArithmeticException. “Line 3” is skipped because it comes after the exception line. Control jumps to the catch block, so “Line 4” prints. After the try-catch, “Line 5” prints. The key point is that “Line 3” never executes because it is in the try block after the exception.

Find the Output

Question 10: What will be the output if no exception occurs?

try { System.out.println(“A”); int x = 10 / 2; System.out.println(“B”); } catch (ArithmeticException e) { System.out.println(“C”); } System.out.println(“D”);

Output:

A B D

Explanation: Since 10 / 2 does NOT cause any exception (dividing by 2 is perfectly fine), all lines in the try block execute normally: “A” prints, the division happens, “B” prints. Because no exception occurred, the catch block is completely skipped. “C” does NOT print. After the try-catch, “D” prints. Remember: if no exception occurs, the catch block is ignored entirely.

Multiple Catch Blocks

Sometimes, the code inside a try block can throw more than one type of exception. In such cases, you can write multiple catch blocks, one for each type of exception. When an exception occurs, Java checks each catch block in order and executes the first one that matches the exception type.

try { // Code that might throw different exceptions } catch (ExceptionType1 e1) { // Handle ExceptionType1 } catch (ExceptionType2 e2) { // Handle ExceptionType2 } catch (ExceptionType3 e3) { // Handle ExceptionType3 }

Let me show you a practical example:

public class Main { public static void main(String[] args) { try { String str = “abc”; int num = Integer.parseInt(str); // NumberFormatException int[] arr = new int[3]; arr[5] = 10; // Would be ArrayIndexOutOfBoundsException (but never reached) int result = 10 / 0; // Would be ArithmeticException (but never reached) } catch (NumberFormatException e) { System.out.println(“Caught NumberFormatException: ” + e.getMessage()); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(“Caught ArrayIndexOutOfBoundsException: ” + e.getMessage()); } catch (ArithmeticException e) { System.out.println(“Caught ArithmeticException: ” + e.getMessage()); } System.out.println(“Program continues…”); } }

Output:

Caught NumberFormatException: For input string: “abc” Program continues…

In this example, the first line in the try block causes a NumberFormatException. The remaining lines in the try block are skipped. Java checks the first catch block: is it NumberFormatException? Yes! So it executes that catch block and skips the other catch blocks. Only ONE catch block executes per exception, even if multiple catch blocks are written.

Important Rule: Order of Catch Blocks Matters

This is a very common exam question. Catch blocks must be ordered from most specific to most general. You cannot put a parent exception class before a child exception class. If you do, the compiler will give an error.

// WRONG – Compile error! Exception is parent of ArithmeticException try { int x = 10 / 0; } catch (Exception e) { // Parent class first – WRONG! System.out.println(“Exception”); } catch (ArithmeticException e) { // Child class second – UNREACHABLE! System.out.println(“ArithmeticException”); } // CORRECT – Child class first, then parent class try { int x = 10 / 0; } catch (ArithmeticException e) { // Child class first – CORRECT! System.out.println(“ArithmeticException”); } catch (Exception e) { // Parent class second – CORRECT! System.out.println(“Exception”); }

Why does Java enforce this? Because if the parent class catch comes first, it will catch ALL exceptions (including child class exceptions), making the child class catch block unreachable. Java detects this at compile time and gives an error. Always put the most specific (child) exception types first and the most general (parent) types last.

Important Notes to Remember for Exam:
1. You can write multiple catch blocks after a single try block.
2. Only ONE catch block executes per exception (the first matching one).
3. Catch blocks must be ordered from most specific to most general (child to parent).
4. Putting a parent exception catch before a child exception catch causes a compile error (unreachable code).
5. Exception is the parent class of most exceptions, so it should be the last catch block.
6. After the first matching catch block runs, the remaining catch blocks are skipped.
MCQ

Question 11: Which of the following multiple catch block arrangements will compile successfully?

A) catch(Exception e) then catch(ArithmeticException e)    B) catch(ArithmeticException e) then catch(Exception e)    C) catch(Throwable e) then catch(Exception e)    D) catch(RuntimeException e) then catch(ArithmeticException e)

Answer: B) catch(ArithmeticException e) then catch(Exception e)

This is the only option where the child class comes before the parent class. ArithmeticException is a child of Exception, so this order is correct (specific first, general last). Options A, C, and D all put the parent class first, which makes the child class catch unreachable and causes a compile error. Remember the rule: always from most specific to most general.

True or False

Question 12: When multiple catch blocks are written, all matching catch blocks execute one after another.

Answer: False

Only the first catch block that matches the exception type will execute. After that catch block finishes, control passes to the code after the entire try-catch structure. The remaining catch blocks are completely skipped. Even if an exception matches two catch blocks (which can happen with parent-child relationships), only the first matching one runs.

The finally Block

The finally block is a special block that comes after the try-catch blocks. The code inside the finally block always executes, regardless of whether an exception occurred or not, and regardless of whether the exception was caught or not. Always. No exceptions. This makes it perfect for cleanup operations like closing files, closing database connections, or releasing resources.

try { // Code that might throw an exception } catch (Exception e) { // Handle the exception } finally { // This ALWAYS runs – no matter what }

Let me demonstrate with examples showing all possible scenarios:

// Scenario 1: Exception occurs and is caught try { int x = 10 / 0; } catch (ArithmeticException e) { System.out.println(“Caught exception”); } finally { System.out.println(“Finally runs”); // ALWAYS prints } // Output: Caught exception // Finally runs // Scenario 2: No exception occurs try { int x = 10 / 2; } catch (ArithmeticException e) { System.out.println(“Caught exception”); } finally { System.out.println(“Finally runs”); // ALWAYS prints } // Output: Finally runs // Scenario 3: Exception occurs but is NOT caught (wrong catch type) try { int[] arr = new int[3]; arr[10] = 5; } catch (ArithmeticException e) { System.out.println(“Caught exception”); // Wrong catch type! } finally { System.out.println(“Finally runs”); // STILL prints! } // Output: Finally runs // Exception in thread “main” ArrayIndexOutOfBoundsException…

Notice in Scenario 3 that even when the exception is NOT caught (wrong catch type), the finally block still runs BEFORE the program crashes. This demonstrates how reliable the finally block is.

There is one rare case where finally does NOT execute: if you call System.exit(0) inside the try block, which immediately terminates the entire JVM. Also, if the JVM itself crashes (like an OutOfMemoryError), finally might not run. But in normal circumstances, finally always runs.

You can also use try-finally WITHOUT a catch block:

try { int x = 10 / 0; } finally { System.out.println(“Finally runs even without catch”); } // Output: Finally runs even without catch // Exception in thread “main” ArithmeticException: / by zero
Important Notes to Remember for Exam:
1. The finally block always executes regardless of whether an exception occurred or was caught.
2. The finally block is used for cleanup operations (closing files, database connections, etc.).
3. A try block can have either catch or finally or both, but it cannot be alone.
4. System.exit(0) is the only way to prevent finally from running in normal code.
5. If both catch and finally modify a variable, the finally block’s value persists.
6. You can use try-finally without catch (but the exception will still crash the program after finally runs).
7. A very common exam question: “Does finally always execute?” The answer is YES, except for System.exit(0) or JVM crash.
Find the Output

Question 13: What will be the output?

public class Test { public static void main(String[] args) { try { System.out.println(“Try”); int x = 10 / 0; } catch (ArithmeticException e) { System.out.println(“Catch”); } finally { System.out.println(“Finally”); } System.out.println(“After”); } }

Output:

Try Catch Finally After

Explanation: “Try” prints first. Then 10/0 throws ArithmeticException. Control jumps to catch, so “Catch” prints. Then the finally block runs, so “Finally” prints. After the entire try-catch-finally structure, “After” prints. All four lines print in order.

Find the Output

Question 14: What will be the output?

public class Test { public static void main(String[] args) { try { System.out.println(“Try”); int x = 10 / 2; } catch (ArithmeticException e) { System.out.println(“Catch”); } finally { System.out.println(“Finally”); } System.out.println(“After”); } }

Output:

Try Finally After

Explanation: “Try” prints. Since 10/2 does NOT cause any exception, the catch block is skipped. But the finally block still runs regardless, so “Finally” prints. Then “After” prints. Notice that “Catch” does NOT print because no exception occurred. The finally block runs even when there is no exception, which is its key characteristic.

MCQ

Question 15: In which situation does the finally block NOT execute?

A) When an exception is caught    B) When no exception occurs    C) When System.exit(0) is called in the try block    D) When the exception is not caught

Answer: C) When System.exit(0) is called in the try block

System.exit(0) immediately terminates the Java Virtual Machine. When the JVM shuts down, no more code runs, including the finally block. In all other scenarios (exception caught, no exception, exception not caught), the finally block runs. Options A, B, and D are all situations where finally DOES execute. Only System.exit(0) can prevent it.

The throw Keyword

So far, exceptions were thrown automatically by Java when something went wrong (like dividing by zero). But Java also allows you to manually throw an exception using the throw keyword. This is useful when you want to enforce certain rules in your code.

The syntax is simple:

throw new ExceptionType(“Error message”);

Notice that we use new because we are creating a new exception object. Let me show you a practical example:

class Student { int age; void setAge(int age) { if (age < 0) { throw new IllegalArgumentException("Age cannot be negative!"); } if (age > 150) { throw new IllegalArgumentException(“Age cannot be more than 150!”); } this.age = age; System.out.println(“Age set to: ” + age); } } public class Main { public static void main(String[] args) { Student s = new Student(); try { s.setAge(20); // Valid s.setAge(-5); // Throws exception } catch (IllegalArgumentException e) { System.out.println(“Error: ” + e.getMessage()); } System.out.println(“Program continues…”); } }

Output:

Age set to: 20 Error: Age cannot be negative! Program continues…

When we call setAge(-5), the condition age < 0 is true, so we manually throw an IllegalArgumentException with a descriptive message. The method stops executing at that point (the line this.age = age is never reached for the invalid input). The exception is caught in the main method's catch block.

Important Notes to Remember for Exam:
1. throw is used to manually throw an exception. It is used INSIDE a method or block.
2. You must create a new exception object using new: throw new ExceptionType("message").
3. You can throw both checked and unchecked exceptions.
4. After throw executes, the remaining code in that block is skipped.
5. throw (lowercase) is different from throws (lowercase with 's') - they do different things!
6. Common use: validating input and throwing exceptions for invalid data.
MCQ

Question 16: What is the correct syntax to manually throw an exception?

A) throw Exception("message")    B) throw new Exception("message")    C) throws new Exception("message")    D) throw ExceptionType.message

Answer: B) throw new Exception("message")

You must use the new keyword to create an exception object because exceptions are objects in Java. The correct syntax is throw new ExceptionType("message"). Option A is wrong because it does not use new. Option C is wrong because throws is a different keyword used in method declarations, not for throwing exceptions. Option D is wrong syntax.

See also  Introduction to Object-Oriented Programming (OOP): Detailed Notes, Examples & Practice Questions (Object Oriented Programming)
Find the Output

Question 17: What will be the output?

public class Test { static void check(int x) { if (x < 0) { throw new RuntimeException("Negative value"); } System.out.println("Value is: " + x); } public static void main(String[] args) { try { check(10); check(-5); check(20); } catch (RuntimeException e) { System.out.println(e.getMessage()); } } }

Output:

Value is: 10 Negative value

Explanation: check(10) passes the condition (10 is not negative), so "Value is: 10" prints. check(-5) fails the condition, so it throws RuntimeException. The line "Value is: -5" is skipped because throw stops execution. The exception is caught in the catch block, which prints "Negative value". check(20) never runs because control went to the catch block and then continues after the try-catch. So "Value is: 20" does NOT print.

The throws Keyword

Now let me explain the throws keyword. Notice the 's' at the end! This is different from throw. While throw actually throws an exception, throws is used in the method declaration to indicate that this method might throw certain exceptions. It is basically a warning sign on the method that says: "Calling this method might cause these exceptions, so be prepared to handle them."

The throws keyword is mainly used for checked exceptions. Remember, the compiler forces you to handle checked exceptions. If your method throws a checked exception and you do not catch it inside the method, you must declare it with throws. Otherwise, the code will not compile.

returnType methodName() throws ExceptionType1, ExceptionType2 { // Method body that might throw exceptions }

Let me show you a clear example:

import java.io.*; class FileReaderDemo { // This method declares that it might throw IOException void readFile(String filename) throws IOException { FileInputStream fis = new FileInputStream(filename); int data = fis.read(); System.out.println("Data: " + data); fis.close(); } } public class Main { public static void main(String[] args) { FileReaderDemo demo = new FileReaderDemo(); try { demo.readFile("nonexistent.txt"); } catch (IOException e) { System.out.println("File error: " + e.getMessage()); } System.out.println("Program continues..."); } }

Output:

File error: nonexistent.txt (No such file or directory) Program continues...

In this example, FileInputStream constructor can throw a checked FileNotFoundException (which is a subclass of IOException). Since we do not catch this inside the readFile method, we must declare it with throws IOException. The caller of this method (main method) then handles it using try-catch.

You can declare multiple exceptions separated by commas:

void method() throws IOException, SQLException, ClassNotFoundException { // ... }

What happens if you do NOT use throws for a checked exception?

// This will NOT compile! void readFile(String filename) { FileInputStream fis = new FileInputStream(filename); // COMPILE ERROR! // Unhandled exception type FileNotFoundException }

The compiler gives an error because FileNotFoundException is a checked exception and you neither caught it nor declared it with throws. You have two choices: wrap it in try-catch, or declare it with throws.

Important Notes to Remember for Exam:
1. throws is used in the method declaration, not inside the method body.
2. throw is used inside a method to actually throw an exception.
3. throws is mainly used for checked exceptions (compiler enforces it).
4. If a method throws a checked exception, you must either catch it inside the method or declare it with throws.
5. You can declare multiple exceptions: throws IOException, SQLException.
6. Using throws does NOT handle the exception. It just passes the responsibility to the caller.
7. The caller of a method with throws must also handle or declare the exception.
MCQ

Question 18: What is the purpose of the throws keyword in a method declaration?

A) To throw an exception inside the method    B) To declare that the method might throw certain exceptions, passing handling responsibility to the caller    C) To catch exceptions inside the method    D) To execute cleanup code

Answer: B) To declare that the method might throw certain exceptions, passing handling responsibility to the caller

The throws keyword does NOT throw an exception (that is throw). It does NOT catch exceptions (that is catch). It does NOT execute cleanup code (that is finally). What throws does is declare in the method signature that this method might throw certain exceptions. It tells the caller: "You need to handle these exceptions when you call this method." The responsibility of handling is transferred to the caller.

True or False

Question 19: The throws keyword is used to handle a checked exception inside the method where it occurs.

Answer: False

The throws keyword does NOT handle the exception. It only declares that the method might throw certain exceptions. The actual handling must be done by the caller of the method using a try-catch block. If you want to handle the exception inside the method itself, you should use try-catch, not throws. This is a very important distinction that examiners test frequently.

MCQ

Question 20: What will happen if a method throws a checked exception but does not declare it with throws and does not catch it with try-catch?

A) The exception is ignored    B) Compile-time error    C) Runtime error    D) The exception is automatically handled

Answer: B) Compile-time error

For checked exceptions, the compiler enforces that you must either catch the exception (using try-catch) or declare it (using throws). If you do neither, the compiler will give an error saying "unhandled exception type." This compile-time checking is exactly why they are called "checked" exceptions. The compiler checks for them before the program can run.

Difference Between throw and throws

This comparison is asked very frequently in exams. Let me make it crystal clear.

Featurethrowthrows
PurposeActually throws an exceptionDeclares that a method might throw exceptions
Where usedInside a method or blockIn the method declaration (signature)
What followsAn exception object: throw new Exception()A list of exception classes: throws Exception1, Exception2
NumberThrows ONE exception at a timeCan declare MULTIPLE exceptions
Effect on codeStops execution of remaining code in the blockDoes not stop execution; only a declaration
Checked vs UncheckedCan throw both typesMainly used for checked exceptions
AnalogyActually pressing the alarm buttonPutting a sign that says "alarm may ring"
Fill in the Blank

Question 21: The ________ keyword is used inside a method to actually throw an exception, while the ________ keyword is used in the method declaration to indicate possible exceptions.

Answer: throw, throws

throw (without 's') is the action keyword used inside a method body to create and throw an exception object. throws (with 's') is the declaration keyword used in the method signature to list the exceptions that the method might throw. Do not confuse these two! One common memory trick: "throw" is short because it does a small action. "throws" has an 's' because it lists multiple exception types.

Throwing Checked vs Unchecked Exceptions

There is an important difference in how Java treats manually thrown checked exceptions versus unchecked exceptions.

Throwing an unchecked exception: You can throw it anywhere without declaring it with throws.

void checkAge(int age) { if (age < 0) { // No throws needed - RuntimeException is unchecked throw new IllegalArgumentException("Age cannot be negative"); } }

Throwing a checked exception: You MUST either catch it or declare it with throws.

// WRONG - Compile error! void readFile() { throw new IOException("File not found"); // Checked exception not declared! } // CORRECT - Declared with throws void readFile() throws IOException { throw new IOException("File not found"); } // ALSO CORRECT - Caught with try-catch void readFile() { try { throw new IOException("File not found"); } catch (IOException e) { System.out.println(e.getMessage()); } }
Important Notes to Remember for Exam:
1. Throwing an unchecked exception (subclass of RuntimeException) does NOT require throws declaration.
2. Throwing a checked exception (subclass of Exception but not RuntimeException) REQUIRES either throws or try-catch.
3. If you are unsure whether an exception is checked or unchecked, check if it extends RuntimeException.

User-Defined (Custom) Exceptions

Java has many built-in exception classes, but sometimes they are not enough to describe the specific errors in your application. For example, if you are writing a student management system, you might want an InvalidGradeException or an InsufficientFundsException. Java allows you to create your own exception classes. These are called user-defined exceptions or custom exceptions.

Creating a custom exception is very simple. You just create a class that extends one of the existing exception classes:

  • For a checked custom exception: extend Exception
  • For an unchecked custom exception: extend RuntimeException
// Custom checked exception class InvalidGradeException extends Exception { // Constructor that accepts a message InvalidGradeException(String message) { super(message); // Pass the message to the Exception constructor } // Optional: a constructor without message InvalidGradeException() { super("Invalid grade!"); } }

Now let me use this custom exception in a complete program:

class InvalidGradeException extends Exception { InvalidGradeException(String message) { super(message); } } class Student { String name; double grade; // Must declare throws because InvalidGradeException extends Exception (checked) void setGrade(double grade) throws InvalidGradeException { if (grade < 0 || grade > 100) { throw new InvalidGradeException( "Grade " + grade + " is invalid. Must be between 0 and 100." ); } this.grade = grade; System.out.println(name + "'s grade set to: " + grade); } } public class Main { public static void main(String[] args) { Student s = new Student(); s.name = "Abebe"; try { s.setGrade(85); // Valid s.setGrade(-10); // Invalid - throws custom exception s.setGrade(95); // This never runs } catch (InvalidGradeException e) { System.out.println("Error: " + e.getMessage()); } System.out.println("Program continues..."); } }

Output:

Abebe's grade set to: 85 Error: Grade -10.0 is invalid. Must be between 0 and 100. Program continues...

See how we created a meaningful exception type that clearly describes the problem? Anyone reading this code understands exactly what kind of error can happen. This is much better than throwing a generic IllegalArgumentException.

If you want an unchecked custom exception, extend RuntimeException instead:

// Custom unchecked exception - no throws declaration needed class InvalidAgeException extends RuntimeException { InvalidAgeException(String message) { super(message); } } class Student { void setAge(int age) { if (age < 0 || age > 120) { // No throws needed - RuntimeException is unchecked throw new InvalidAgeException("Age " + age + " is invalid."); } System.out.println("Age set to: " + age); } }
Important Notes to Remember for Exam:
1. A custom exception is created by extending Exception (checked) or RuntimeException (unchecked).
2. You should provide at least a constructor that accepts a String message and calls super(message).
3. If your custom exception extends Exception, you MUST use throws or try-catch when throwing it.
4. If your custom exception extends RuntimeException, no throws declaration is needed.
5. Custom exceptions make your code more readable and meaningful.
6. The exam often asks you to write a complete custom exception class and use it in a program. Practice this!
MCQ

Question 22: How do you create a custom checked exception?

A) Implement the Exception interface    B) Extend the RuntimeException class    C) Extend the Exception class    D) Use the custom keyword

Answer: C) Extend the Exception class

To create a checked custom exception, you extend the Exception class. If you extended RuntimeException, it would be an unchecked exception (option B is wrong). There is no "Exception interface" to implement (option A is wrong). There is no "custom" keyword in Java (option D is wrong). The standard way is: class MyException extends Exception { }

Short Answer

Question 23: Write a custom exception class called InsufficientBalanceException that extends Exception and has a constructor accepting a message. Then write a BankAccount class with a withdraw method that throws this exception if the withdrawal amount exceeds the balance.

// Custom checked exception class InsufficientBalanceException extends Exception { InsufficientBalanceException(String message) { super(message); } } // BankAccount class using the custom exception class BankAccount { String accountHolder; double balance; BankAccount(String name, double initialBalance) { this.accountHolder = name; this.balance = initialBalance; } void withdraw(double amount) throws InsufficientBalanceException { if (amount > balance) { throw new InsufficientBalanceException( "Cannot withdraw " + amount + ". Balance is only " + balance ); } balance = balance - amount; System.out.println("Withdrawn: " + amount + ". New balance: " + balance); } } // Testing public class Main { public static void main(String[] args) { BankAccount acc = new BankAccount("Abebe", 5000); try { acc.withdraw(2000); // Success acc.withdraw(4000); // Throws exception } catch (InsufficientBalanceException e) { System.out.println("Transaction failed: " + e.getMessage()); } } }

Output:

Withdrawn: 2000.0. New balance: 3000.0 Transaction failed: Cannot withdraw 4000.0. Balance is only 3000.0

Nested try Blocks

Java allows you to put a try block inside another try block. This is called nested try blocks. You use this when different parts of your code need different levels of exception handling.

try { // Outer try int[] arr = {1, 2, 3}; System.out.println(arr[0]); try { // Inner try int x = 10 / 0; // Exception in inner try } catch (ArithmeticException e) { System.out.println("Inner catch: " + e.getMessage()); } System.out.println(arr[5]); // Exception in outer try } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Outer catch: " + e.getMessage()); }

Output:

1 Inner catch: / by zero Outer catch: Index 5 out of bounds for length 3

The rule is: if an exception occurs in the inner try block, the inner catch blocks are checked first. If none of them match, the exception propagates to the outer try block and the outer catch blocks are checked. This propagation continues outward until a matching catch is found or the program crashes.

Find the Output

Question 24: What will be the output?

try { System.out.println("Outer try"); try { System.out.println("Inner try"); int x = 10 / 0; System.out.println("After division"); } catch (ArithmeticException e) { System.out.println("Inner catch"); } System.out.println("After inner try-catch"); } catch (Exception e) { System.out.println("Outer catch"); } System.out.println("End");

Output:

Outer try Inner try Inner catch After inner try-catch End

Explanation: "Outer try" prints. Then "Inner try" prints. The division by zero throws ArithmeticException. The inner catch matches, so "Inner catch" prints. After the inner try-catch finishes, "After inner try-catch" prints (back in the outer try). No exception occurs in the outer try at this point, so "Outer catch" is skipped. "End" prints. The inner catch handled the exception, so it never reached the outer catch.

Common Exception Classes in Java

Let me list the most common exception classes that you need to know for your exam. I will explain what each one means and when it occurs.

See also  Data Communication: Complete Lesson for Ethiopian Students
Exception ClassTypeWhen It Occurs
ArithmeticExceptionUncheckedIllegal arithmetic operation like dividing by zero
NullPointerExceptionUncheckedTrying to use a reference variable that points to null
ArrayIndexOutOfBoundsExceptionUncheckedAccessing an array with an invalid index
NumberFormatExceptionUncheckedTrying to convert a non-numeric string to a number
ClassCastExceptionUncheckedTrying to cast an object to an incompatible type
StringIndexOutOfBoundsExceptionUncheckedAccessing a character in a String with an invalid index
StackOverflowErrorErrorMethod calls itself infinitely (infinite recursion)
OutOfMemoryErrorErrorJVM runs out of memory
IOExceptionCheckedGeneral I/O failure (file operations, network)
FileNotFoundExceptionCheckedTrying to access a file that does not exist
SQLExceptionCheckedDatabase access error
InterruptedExceptionCheckedA thread is interrupted while waiting/sleeping
MCQ

Question 25: Which exception occurs when you try to call a method on a null reference variable?

A) ArithmeticException    B) NumberFormatException    C) NullPointerException    D) ClassCastException

Answer: C) NullPointerException

NullPointerException occurs when you try to use an object reference that is null. For example, if you write String s = null; and then s.length(), Java throws NullPointerException because s does not point to any actual String object. This is one of the most common runtime exceptions in Java programs.

MCQ

Question 26: Which exception occurs when Integer.parseInt("abc") is executed?

A) ArithmeticException    B) NullPointerException    C) NumberFormatException    D) IOException

Answer: C) NumberFormatException

Integer.parseInt("abc") tries to convert the string "abc" to an integer. Since "abc" is not a valid number, Java throws a NumberFormatException. This is a subclass of IllegalArgumentException, which is a subclass of RuntimeException, making it an unchecked exception. If the string were "123", it would convert successfully without any exception.

Exception Propagation

Exception propagation (also called exception bubbling) is the process by which an exception moves up through the call stack when it is not caught in the current method. Let me explain this clearly.

When an exception occurs in a method and the method does not catch it, the exception is not lost. Instead, Java automatically passes (propagates) the exception to the method that called this method. If that method also does not catch it, it propagates further up, and so on, until it reaches the main method. If even main does not catch it, the JVM terminates the program and prints the error.

Exception Propagation (Uncaught Exception) main() calls methodA() calls methodB() calls methodC() methodC(): exception occurs here! | | not caught, propagates up v methodB(): receives exception, not caught | | not caught, propagates up v methodA(): receives exception, not caught | | not caught, propagates up v main(): receives exception, not caught | | not caught, propagates up v JVM: prints error and terminates program

For unchecked exceptions, this propagation happens automatically. For checked exceptions, the compiler forces you to either catch or declare at each level.

class Demo { static void methodC() { int x = 10 / 0; // ArithmeticException occurs System.out.println("This never prints"); } static void methodB() { methodC(); // Exception propagates here System.out.println("This never prints"); } static void methodA() { methodB(); // Exception propagates here System.out.println("This never prints"); } public static void main(String[] args) { methodA(); // Exception propagates here System.out.println("This never prints"); } }

Output:

Exception in thread "main" java.lang.ArithmeticException: / by zero at Demo.methodC(Demo.java:3) at Demo.methodB(Demo.java:8) at Demo.methodA(Demo.java:13) at Demo.main(Demo.java:18)

The stack trace shows the full propagation path: the exception started at methodC (line 3), propagated to methodB (line 8), then to methodA (line 13), then to main (line 18). None of the "This never prints" lines executed because the exception kept propagating upward.

Now if we catch the exception at any level, the propagation stops there:

class Demo { static void methodC() { int x = 10 / 0; } static void methodB() { methodC(); // Exception propagates here } static void methodA() { try { methodB(); // Exception propagates here but is caught } catch (ArithmeticException e) { System.out.println("Caught in methodA: " + e.getMessage()); } System.out.println("methodA continues"); } public static void main(String[] args) { methodA(); System.out.println("main continues"); } }

Output:

Caught in methodA: / by zero methodA continues main continues

The propagation stopped at methodA because that is where we caught it. The program continues normally from there.

Important Notes to Remember for Exam:
1. Exception propagation is the process of an exception moving up the call stack when not caught.
2. Unchecked exceptions propagate automatically.
3. Checked exceptions must be declared with throws at each level of propagation.
4. Propagation stops when a catch block matches the exception type.
5. If the exception reaches main() and is not caught, the JVM terminates the program.
6. The stack trace shows the exact path of propagation from the origin to the top.
MCQ

Question 27: Where does an unchecked exception propagate if it is not caught in the method where it occurred?

A) It is silently ignored    B) It automatically propagates to the caller method    C) It is stored in a buffer    D) It is converted to a checked exception

Answer: B) It automatically propagates to the caller method

When an unchecked exception is not caught in the current method, Java automatically passes it up to the method that called the current method. This continues up the call stack until either a matching catch block is found or the exception reaches the main method and causes the JVM to terminate. The programmer does not need to write any special code for this propagation; it happens automatically for unchecked exceptions.

Exercises with Answers

Exercise 1: Write a program that takes a string input and converts it to an integer using Integer.parseInt(). Handle the NumberFormatException that occurs if the string is not a valid number. Also handle any other unexpected exceptions using a general Exception catch block. Use a finally block to print a completion message.
public class Main { public static void main(String[] args) { String input = "Hello World"; // Try changing to "123" try { System.out.println("Converting: " + input); int number = Integer.parseInt(input); System.out.println("Converted successfully: " + number); } catch (NumberFormatException e) { System.out.println("Error: '" + input + "' is not a valid number."); System.out.println("Details: " + e.getMessage()); } catch (Exception e) { System.out.println("Unexpected error: " + e.getMessage()); } finally { System.out.println("Conversion attempt completed."); } System.out.println("Program continues..."); } }

Output (with "Hello World"):

Converting: Hello World Error: 'Hello World' is not a valid number. Details: For input string: "Hello World" Conversion attempt completed. Program continues...

Output (with "123"):

Converting: 123 Converted successfully: 123 Conversion attempt completed. Program continues...
Exercise 2: Write a program with a method called divide(int a, int b) that throws an ArithmeticException if b is zero. Call this method from main with different values and handle the exception. Also show what happens when no exception occurs.
public class Main { static void divide(int a, int b) { if (b == 0) { throw new ArithmeticException("Division by zero is not allowed!"); } System.out.println(a + " / " + b + " = " + (a / b)); } public static void main(String[] args) { // Test 1: Valid division try { divide(20, 4); } catch (ArithmeticException e) { System.out.println("Error: " + e.getMessage()); } // Test 2: Division by zero try { divide(10, 0); } catch (ArithmeticException e) { System.out.println("Error: " + e.getMessage()); } // Test 3: Another valid division try { divide(15, 3); } catch (ArithmeticException e) { System.out.println("Error: " + e.getMessage()); } } }

Output:

20 / 4 = 5 Error: Division by zero is not allowed! 15 / 3 = 5
Exercise 3: Create a custom unchecked exception called InvalidEmailException. Write a method validateEmail(String email) that throws this exception if the email does not contain "@" or does not contain ".". Write a main method to test with both valid and invalid emails.
// Custom unchecked exception class InvalidEmailException extends RuntimeException { InvalidEmailException(String message) { super(message); } } class EmailValidator { static void validateEmail(String email) { if (email == null || email.isEmpty()) { throw new InvalidEmailException("Email cannot be empty!"); } if (!email.contains("@")) { throw new InvalidEmailException("Email must contain '@' symbol!"); } if (!email.contains(".")) { throw new InvalidEmailException("Email must contain '.' character!"); } System.out.println("Valid email: " + email); } } public class Main { public static void main(String[] args) { String[] emails = {"abebe@gmail.com", "tigistyahoo", "yohannes@aau", "", "hana@etu.edu.et"}; for (String email : emails) { try { EmailValidator.validateEmail(email); } catch (InvalidEmailException e) { System.out.println("Invalid: " + email + " - " + e.getMessage()); } } } }

Output:

Valid email: abebe@gmail.com Invalid: tigistyahoo - Email must contain '@' symbol! Invalid: yohannes@aau - Email must contain '.' character! Invalid: - Email cannot be empty! Valid email: hana@etu.edu.et
Exercise 4: Find and correct all errors in the following code:
public class Test { static void method() { throws IOException System.out.println("Hello"); } public static void main(String[] args) { try { method(); } catch (IOException e) { System.out.println("Caught"); } catch (Exception e) { System.out.println("General"); } catch (IOException e) { System.out.println("Duplicate"); } } }

Errors found:

Error 1: The throws IOException is written inside the method body. The throws clause must be in the method declaration (in the method signature), not inside the method body. Also, import java.io.IOException; is missing.

Error 2: There are duplicate catch blocks for IOException. You cannot have two catch blocks for the same exception type. The second catch (IOException e) block is unreachable and causes a compile error.

Corrected code:

import java.io.IOException; public class Test { static void method() throws IOException { // throws in method signature System.out.println("Hello"); } public static void main(String[] args) { try { method(); } catch (IOException e) { System.out.println("Caught IO"); } catch (Exception e) { // Only one Exception catch System.out.println("General"); } // Removed the duplicate IOException catch } }

More Practice Questions for Exam

Find the Output

Question 28: What will be the output?

public class Test { public static void main(String[] args) { try { try { System.out.println("A"); int x = 10 / 0; } catch (ArithmeticException e) { System.out.println("B"); int[] arr = new int[2]; arr[5] = 10; } finally { System.out.println("C"); } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("D"); } System.out.println("E"); } }

Output:

A B C D E

Explanation: "A" prints. Division by zero throws ArithmeticException in the inner try. "B" prints in the inner catch. Then inside that catch, arr[5] throws ArrayIndexOutOfBoundsException. The inner catch does not catch this, so it propagates out of the inner try-catch-finally. But first, the inner finally runs and prints "C". Then the ArrayIndexOutOfBoundsException reaches the outer try-catch, and the outer catch matches, printing "D". After the outer try-catch, "E" prints. Key insight: the finally block of the inner try runs even when an exception occurs inside the catch block.

Find the Output

Question 29: What will be the output?

public class Test { public static void main(String[] args) { int x = 0; try { x = 10; return; } catch (Exception e) { x = 20; } finally { x = 30; System.out.println("x = " + x); } System.out.println("After finally"); } }

Output:

x = 30

Explanation: Inside the try block, x is set to 10, then return is encountered. Normally, return would immediately exit the method. But the finally block MUST run before the method actually returns. So the finally block executes, setting x to 30 and printing "x = 30". After the finally block, the method returns (the original return is completed). The "After finally" line does NOT print because the method already has a return statement in the try block. The finally block runs even when there is a return in the try block!

Short Answer

Question 30: Explain the complete exception hierarchy in Java with a diagram. List at least two examples for each category (Error, Checked Exception, Unchecked Exception).

Answer:

Throwable / \ / \ v v Error Exception / \ / \ v v v v OutOfMemory StackOverflow RuntimeException IOException Error Error / | \ / \ v v v v v Arithmetic NullPointer ArrayIndex FileNotFound SQLException Exception Exception OutOfBounds Exception Exception

Error examples: OutOfMemoryError, StackOverflowError. These are serious system problems that should not be handled.

Checked Exception examples: IOException, FileNotFoundException, SQLException, ClassNotFoundException. The compiler forces handling.

Unchecked Exception examples: ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException, ClassCastException. The compiler does not force handling.

List and Explain

Question 31: List the five keywords used in Java exception handling and explain each with one sentence.

Answer:

1. try: A block that contains code that might throw an exception; if an exception occurs, control jumps to catch.

2. catch: A block that catches and handles a specific type of exception thrown by the try block.

3. finally: A block that always executes after try-catch, regardless of whether an exception occurred or was caught, used for cleanup.

4. throw: A keyword used inside a method to manually throw an exception object.

5. throws: A keyword used in a method declaration to declare that the method might throw certain checked exceptions.

Find the Output

Question 32: What will be the output?

class Test { static void m1() throws Exception { throw new Exception("From m1"); } static void m2() throws Exception { m1(); } static void m3() throws Exception { m2(); } public static void main(String[] args) { try { m3(); } catch (Exception e) { System.out.println(e.getMessage()); } } }

Output:

From m1

Explanation: The exception originates in m1, propagates to m2 (which declares throws), then propagates to m3 (which also declares throws), then propagates to main where it is finally caught by the catch block. Since all methods properly declared the checked exception with throws, the code compiles. The catch block prints the message "From m1" which was set when the exception was created. The propagation path is m1 -> m2 -> m3 -> main, and it stops at main because that is where the catch block is.

Final Exam Tips for Exception Handling:
1. Memorize the five keywords: try, catch, finally, throw, throws. Know exactly what each one does.
2. Memorize the exception hierarchy: Throwable -> Error and Exception -> RuntimeException (unchecked) and others (checked).
3. Know which exceptions are checked (IOException, FileNotFoundException, SQLException) and which are unchecked (ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException).
4. Remember: catch blocks go from most specific to most general (child to parent). Parent first = compile error.
5. The finally block always executes (except System.exit(0)). Even with return in try, finally runs first.
6. After an exception in try, remaining try lines are skipped. Only ONE catch block executes.
7. throw = inside method, throws one exception. throws = in method declaration, lists possible exceptions.
8. Custom exception: extend Exception for checked, extend RuntimeException for unchecked. Always call super(message).
9. Exception propagation: unchecked propagates automatically, checked must be declared with throws at each level.
10. Practice "find the output" questions with nested try-catch-finally. These are very common in exams.
11. Remember the useful exception object methods: getMessage(), toString(), printStackTrace().
12. When writing custom exceptions, always include a constructor that accepts a String message parameter.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top