0
0
Kotlinprogramming~15 mins

Multiple catch blocks in Kotlin - Deep Dive

Choose your learning style9 modes available
Overview - Multiple catch blocks
What is it?
Multiple catch blocks in Kotlin allow you to handle different types of errors separately in a try-catch structure. Each catch block can catch a specific exception type and run code to fix or respond to that error. This helps keep your program running smoothly even when unexpected problems happen. It is like having different helpers ready for different problems.
Why it matters
Without multiple catch blocks, you would have to handle all errors in one place, making your code messy and hard to understand. Different errors often need different fixes, so separating them helps you write clearer and safer programs. This reduces crashes and bugs, making your apps more reliable and user-friendly.
Where it fits
Before learning multiple catch blocks, you should know basic try-catch error handling in Kotlin. After this, you can learn about custom exceptions and how to create your own error types for even better control.
Mental Model
Core Idea
Multiple catch blocks let you catch and handle different errors separately, so each problem gets the right fix.
Think of it like...
Imagine you have a toolbox with different tools for different problems: a hammer for nails, a screwdriver for screws, and pliers for wires. Multiple catch blocks are like choosing the right tool for each problem that happens in your code.
┌─────────────┐
│   try {     }│
├─────────────┤
│ catch (A) { }│
├─────────────┤
│ catch (B) { }│
├─────────────┤
│ catch (C) { }│
└─────────────┘

Each catch block handles a different exception type.
Build-Up - 7 Steps
1
FoundationBasic try-catch structure
🤔
Concept: Learn how to use a simple try-catch block to handle errors.
In Kotlin, you write code that might fail inside a try block. If an error happens, the catch block runs to handle it. Example: try { val number = "abc".toInt() // This will cause an error } catch (e: NumberFormatException) { println("Not a valid number") }
Result
The program prints: Not a valid number
Understanding the basic try-catch is essential because it shows how Kotlin catches errors to prevent crashes.
2
FoundationException types in Kotlin
🤔
Concept: Know that different errors have different exception types.
Kotlin has many exception types like NumberFormatException, NullPointerException, and IOException. Each represents a different problem. Example: try { val text: String? = null println(text!!.length) // Causes NullPointerException } catch (e: NullPointerException) { println("Null value found") }
Result
The program prints: Null value found
Recognizing exception types helps you catch the right error and respond properly.
3
IntermediateUsing multiple catch blocks
🤔Before reading on: Do you think Kotlin runs all catch blocks or stops after the first matching one? Commit to your answer.
Concept: Learn how to write several catch blocks to handle different exceptions separately.
You can write many catch blocks after one try block. Kotlin checks each catch in order and runs the first one that matches the error. Example: try { val input = "abc" val number = input.toInt() println(number) } catch (e: NumberFormatException) { println("Number format error") } catch (e: Exception) { println("Some other error") }
Result
The program prints: Number format error
Knowing that Kotlin stops at the first matching catch block prevents confusion about error handling order.
4
IntermediateOrder of catch blocks matters
🤔Before reading on: Should you put general exceptions before specific ones? Commit to your answer.
Concept: Understand that catch blocks are checked top to bottom, so order affects which block runs.
If you put a general exception like Exception before a specific one like NumberFormatException, the specific one will never run. Wrong order example: try { val input = "abc" val number = input.toInt() } catch (e: Exception) { println("General error") } catch (e: NumberFormatException) { println("Number format error") } Correct order example: try { val input = "abc" val number = input.toInt() } catch (e: NumberFormatException) { println("Number format error") } catch (e: Exception) { println("General error") }
Result
In the wrong order, the program prints: General error In the correct order, it prints: Number format error
Understanding catch order prevents bugs where specific errors are hidden by general handlers.
5
IntermediateCatching multiple exceptions in one block
🤔
Concept: Learn how to catch several exception types in a single catch block using Kotlin's syntax.
Kotlin lets you catch multiple exceptions together using a pipe (|) symbol. Example: try { // code that may throw IOException or NumberFormatException } catch (e: IOException | NumberFormatException) { println("Handled IO or number format error") }
Result
If either IOException or NumberFormatException occurs, the catch block runs.
Knowing this syntax helps write cleaner code when the same handling applies to multiple errors.
6
AdvancedRe-throwing exceptions after catch
🤔Before reading on: Do you think you can fix all errors inside catch blocks? Commit to your answer.
Concept: Sometimes you catch an exception to log or partially handle it, then throw it again to let higher code handle it too.
You can use throw inside a catch block to pass the exception up. Example: try { val input = "abc" val number = input.toInt() } catch (e: NumberFormatException) { println("Logging error") throw e // Pass error up }
Result
The program logs the error, then the exception continues to propagate.
Understanding re-throwing helps build layered error handling where different parts of the program respond appropriately.
7
ExpertException hierarchy and catch specificity
🤔Before reading on: Does catching a superclass exception catch all its subclasses? Commit to your answer.
Concept: Kotlin exceptions form a class hierarchy; catching a superclass catches all its subclasses, so specificity matters.
For example, IOException is a superclass of FileNotFoundException. Example: try { // code that throws FileNotFoundException } catch (e: IOException) { println("Caught IOException and subclasses") } catch (e: FileNotFoundException) { println("This block is unreachable") }
Result
The catch block for IOException catches FileNotFoundException, so the specific block never runs.
Knowing exception inheritance prevents unreachable code and helps organize catch blocks correctly.
Under the Hood
When Kotlin runs a try block, it watches for exceptions thrown inside. If an exception occurs, Kotlin looks at each catch block in order. It checks if the exception type matches the catch block's type or is a subclass. The first matching catch block runs, handling the error. If none match, the exception moves up to the caller. This process uses Kotlin's runtime type checking and exception dispatch system.
Why designed this way?
This design follows common programming language patterns to keep error handling clear and efficient. Checking catch blocks in order allows programmers to handle specific errors first, then more general ones. It avoids confusion and unreachable code. The hierarchy-based matching leverages object-oriented principles, making error handling flexible and powerful.
┌─────────────┐
│   try {     }│
│  (code runs)│
└──────┬──────┘
       │
       ▼
  Exception thrown?
       │ Yes
       ▼
┌─────────────┐
│ catch block │
│ 1: matches? │──No──▶ next catch
│   Yes      │
└──────┬──────┘
       │
       ▼
  Run catch block
       │
       ▼
  Continue program
Myth Busters - 4 Common Misconceptions
Quick: Does Kotlin run all catch blocks that match an exception or just the first one? Commit to your answer.
Common Belief:Kotlin runs all catch blocks that match the exception type.
Tap to reveal reality
Reality:Kotlin runs only the first catch block that matches the exception type and skips the rest.
Why it matters:Believing all catch blocks run can lead to writing unreachable code and misunderstanding error flow.
Quick: Can you put a general Exception catch block before a specific one without issues? Commit to your answer.
Common Belief:You can put a general Exception catch block before specific ones without problems.
Tap to reveal reality
Reality:If a general Exception catch block comes first, specific catch blocks after it become unreachable and never run.
Why it matters:This causes bugs where specific errors are not handled properly, leading to incorrect error responses.
Quick: Does catching Exception catch all errors including errors like OutOfMemoryError? Commit to your answer.
Common Belief:Catching Exception catches all errors and problems in the program.
Tap to reveal reality
Reality:Exception does not catch all errors; some serious errors like OutOfMemoryError are subclasses of Throwable but not Exception, so they are not caught.
Why it matters:Assuming all errors are caught can cause programs to miss critical failures and behave unpredictably.
Quick: Does catching multiple exceptions with | mean you can catch unrelated exceptions together? Commit to your answer.
Common Belief:You can catch any exceptions together with | regardless of their relation.
Tap to reveal reality
Reality:You can catch multiple exceptions together with | only if they are unrelated or you want the same handling; but catching unrelated exceptions without care can hide specific error handling needs.
Why it matters:Misusing multi-catch can lead to less precise error handling and harder debugging.
Expert Zone
1
Catch blocks can be used to add context or logging before re-throwing exceptions, enabling layered error handling.
2
The Kotlin compiler enforces unreachable catch block detection, preventing general exceptions from shadowing specific ones.
3
Using sealed classes for custom exceptions can improve exhaustiveness checks in catch blocks, enhancing safety.
When NOT to use
Avoid multiple catch blocks when the error handling is identical for all exceptions; use a single catch block instead. Also, do not catch Throwable unless you have a very good reason, as it includes serious errors that should usually crash the program.
Production Patterns
In production, multiple catch blocks are used to handle recoverable errors differently, such as network failures vs. data parsing errors. Logging and metrics collection often happen in catch blocks. Re-throwing exceptions after partial handling is common to let higher layers decide on fallback or user notification.
Connections
Polymorphism in Object-Oriented Programming
Multiple catch blocks rely on polymorphism to match exception types and subclasses.
Understanding polymorphism helps grasp why catching a superclass exception also catches its subclasses, which is key to organizing catch blocks.
Error Handling in Human Communication
Both involve recognizing different problems and responding appropriately based on type and severity.
Knowing how humans tailor responses to different issues helps appreciate why multiple catch blocks improve program clarity and user experience.
Medical Triage Systems
Multiple catch blocks are like triage, sorting different emergencies to the right specialist.
This connection shows how sorting problems by type leads to better outcomes, whether in medicine or programming.
Common Pitfalls
#1Putting a general Exception catch block before specific ones.
Wrong approach:try { // code } catch (e: Exception) { println("General error") } catch (e: NumberFormatException) { println("Number format error") }
Correct approach:try { // code } catch (e: NumberFormatException) { println("Number format error") } catch (e: Exception) { println("General error") }
Root cause:Misunderstanding that catch blocks are checked in order and that a general catch first blocks later specific catches.
#2Catching Throwable to handle all errors.
Wrong approach:try { // code } catch (e: Throwable) { println("Caught everything") }
Correct approach:try { // code } catch (e: Exception) { println("Caught recoverable errors") }
Root cause:Not knowing that Throwable includes serious errors that should not be caught and handled like normal exceptions.
#3Assuming multiple catch blocks run for one exception.
Wrong approach:try { // code } catch (e: IOException) { println("IO error") } catch (e: Exception) { println("General error") } // Expecting both prints if IOException occurs
Correct approach:try { // code } catch (e: IOException) { println("IO error") } catch (e: Exception) { println("General error") } // Only first matching catch runs
Root cause:Misunderstanding that only the first matching catch block executes.
Key Takeaways
Multiple catch blocks let you handle different error types separately, making your code clearer and safer.
Catch blocks are checked in order, so always put specific exceptions before general ones to avoid unreachable code.
You can catch multiple exceptions in one block if they share the same handling, using Kotlin's multi-catch syntax.
Re-throwing exceptions after catching them allows layered error handling and better control over program flow.
Understanding exception hierarchy is crucial to organizing catch blocks and preventing bugs in error handling.