Exception Handling
try, catch, finally
Throwing Custom Exceptions
Exception:
An exception is an object that represents an error or unexpected condition in a program.
Dart provides a built-in Exception class, but you can also define custom exceptions.
try Block:
The code that may throw an exception is placed inside the try block.
catch Block:
The catch block is used to handle the exception.
You can define a single catch block or multiple blocks to handle different types of exceptions.
on Keyword:
The on keyword is used to catch specific types of exceptions.
finally Block:
The finally block contains code that will always execute, regardless of whether an exception was thrown or not. It is often used for cleanup operations.
Throwing Exceptions:
Exceptions can be explicitly thrown using the throw keyword.
Syntax-
try {
// Code that may throw an exception
} on SpecificException {
// Handle specific exception
} catch (e) {
// Handle any exception
} finally {
// Code that will always execute
}
void main() {
int a = 4,
b = -0;
double c = a / b;
print(c);
}
This demonstrates catching any exception using try and catch.
void main() {
try {
int result = 10 ~/ 0; // Division by zero will throw an exception
print("Result: $result");
} catch (e) {
print("An Exception occurred: $e");
}
}
This demonstrates catching specific exceptions using the on keyword.
void main() {
try {
int result = 10 ~/ 0.0; // Division by zero
print("Result: $result");
} on IntegerDivisionByZeroException {
print("Cannot divide by zero!");
} catch (e) {
print("An unexpected error occurred: $e");
}
}
This demonstrates using a finally block for cleanup, ensuring it always executes.
void main() {
try {
int result = 10 ~/ 0; // Division by zero
print("Result: $result");
} catch (e) {
print("An error occurred: $e");
} finally {
print("Execution complete.");
}
}
This demonstrates defining and throwing a custom exception.
class NegativeNumberException implements Exception {
final String message;
NegativeNumberException(this.message);
@override
String toString() => "NegativeNumberException: $message";
}
void main() {
try {
checkPositive(-5);
} catch (e) {
print(e);
} finally {
print("Execution complete.");
}
}
void checkPositive(int number) {
if (number < 0) {
throw NegativeNumberException("Number $number is negative. Positive numbers only!");
}
print("The number $number is positive.");
}
This demonstrates explicitly throwing exceptions with throw.
void main() {
try {
validateAge(-1);
} catch (e) {
print("Error: $e");
} finally {
print("Validation complete.");
}
}
void validateAge(int age) {
if (age < 0) {
throw Exception("Age cannot be negative!");
}
print("Age is valid: $age");
}
This demonstrates handling multiple types of exceptions.
void main() {
try {
int result = int.parse("invalid"); // This will throw a FormatException
print("Result: $result");
} on FormatException {
print("Input is not a valid number.");
} catch (e) {
print("An unexpected error occurred: $e");
} finally {
print("Execution complete.");
}
}
This demonstrates capturing and printing the stack trace.
void main() {
try {
int result = 10 ~/ 0;
print("Result: $result");
} catch (e, stackTrace) {
print("Error: $e");
print("Stack trace: $stackTrace");
}
}
This demonstrates rethrowing an exception after handling it partially.
void main() {
try {
processFile();
} catch (e) {
print("Unhandled exception: $e");
}
}
void processFile() {
try {
throw Exception("File not found.");
} catch (e) {
print("Caught an exception: $e");
rethrow; // Pass the exception up the call stack
}
}
void main() {
try {
int result = divide(10, 0);
print("Result: $result");
} on IntegerDivisionByZeroException {
print("Cannot divide by zero!");
} catch (e) {
print("An error occurred: $e");
} finally {
print("Execution complete.");
}
}
int divide(int a, int b) {
if (b == 0) {
throw IntegerDivisionByZeroException();
}
return a ~/ b;
}
class NegativeNumberException implements Exception {
String errorMessage() => "Negative numbers are not allowed!";
}
void main() {
try {
checkPositive(-5);
} catch (e) {
print(e);
} finally {
print("Execution complete.");
}
}
void checkPositive(int number) {
if (number < 0) {
throw NegativeNumberException();
} else {
print("The number is positive.");
}
}
In Dart, exception handling can be categorized based on the type of errors handled and how exceptions are managed. Below are the types of exception handling in Dart programming:
These are specific exceptions that the programmer can anticipate and handle explicitly using the on keyword.
Example: Handling FormatException, IntegerDivisionByZeroException, etc.
void main() {
try {
int number = int.parse("abc"); // Throws FormatException
print("Number: $number");
} on FormatException {
print("The input is not a valid number.");
}
}
These are exceptions that are caught generically using the catch block.
It handles any exception regardless of its type.
void main() {
try {
int result = 10 ~/ 0; // Throws IntegerDivisionByZeroException
print("Result: $result");
} catch (e) {
print("An error occurred: $e");
}
}
Dart allows developers to define their own exception classes to handle application-specific errors.
Custom exceptions implement the Exception or Error class.
class CustomException implements Exception {
final String message;
CustomException(this.message);
@override
String toString() => "CustomException: $message";
}
void main() {
try {
throw CustomException("This is a custom exception.");
} catch (e) {
print(e);
}
}
Using both on and catch together allows for more precise exception handling.
on is used to handle specific exceptions, while catch handles all other exceptions.
void main() {
try {
int result = int.parse("invalid"); // Throws FormatException
print("Result: $result");
} on FormatException {
print("Input is not a valid number.");
} catch (e) {
print("An unexpected error occurred: $e");
}
}
The finally block executes code regardless of whether an exception was thrown or caught.
It is typically used for cleanup actions like closing files or releasing resources.
void main() {
try {
int result = 10 ~/ 0; // Throws IntegerDivisionByZeroException
print("Result: $result");
} catch (e) {
print("An error occurred: $e");
} finally {
print("Execution completed, cleanup done.");
}
}
This is useful when you want to log or handle an exception partially and then pass it up the call stack.
void main() {
try {
handleException();
} catch (e) {
print("Rethrown exception caught in main: $e");
}
}
void handleException() {
try {
throw Exception("An error occurred!");
} catch (e) {
print("Caught exception: $e");
rethrow; // Re-throws the exception
}
}
You can capture both the exception and its stack trace using catch with two parameters.
This is helpful for debugging and logging purposes.
void main() {
try {
int result = 10 ~/ 0; // Throws IntegerDivisionByZeroException
print("Result: $result");
} catch (e, stackTrace) {
print("Error: $e");
print("Stack trace: $stackTrace");
}
}