Skip to main content

Command Palette

Search for a command to run...

Bài 3: Cấu Trúc try-catch-finally

Published
5 min readView as Markdown

1. Giới Thiệu

Cấu trúc try-catch-finally là một cơ chế quan trọng trong Java để xử lý ngoại lệ. Nó cho phép bạn giám sát mã có khả năng gây ra ngoại lệ và xử lý chúng một cách hợp lý. Cấu trúc này cũng đảm bảo rằng các hành động cần thiết vẫn được thực hiện dù có ngoại lệ xảy ra hay không.

2. Cấu Trúc Cơ Bản của try-catch-finally

2.1. Cấu Trúc try-catch

Cấu trúc try-catch được sử dụng để giám sát và xử lý ngoại lệ.

  • try: Khối mã có khả năng gây ra ngoại lệ.

  • catch: Khối mã xử lý ngoại lệ nếu có xảy ra.

Ví dụ cơ bản:

public class TryCatchExample {
    public static void main(String[] args) {
        try {
            int result = 10 / 0; // Gây ra ArithmeticException
        } catch (ArithmeticException e) {
            System.err.println("Caught ArithmeticException: " + e.getMessage());
        }
    }
}
2.2. Cấu Trúc try-catch-finally

Khối finally chứa mã sẽ luôn được thực thi, bất kể ngoại lệ có xảy ra hay không.

public class TryCatchFinallyExample {
    public static void main(String[] args) {
        try {
            int result = 10 / 0; // Gây ra ArithmeticException
        } catch (ArithmeticException e) {
            System.err.println("Caught ArithmeticException: " + e.getMessage());
        } finally {
            System.out.println("This block is always executed.");
        }
    }
}

3. Ví Dụ Chi Tiết

3.1. Đọc File với try-catch-finally

Đây là một ví dụ phổ biến trong việc xử lý ngoại lệ khi làm việc với I/O. Chúng ta sẽ sử dụng BufferedReader để đọc file và đảm bảo rằng tài nguyên được giải phóng đúng cách trong khối finally.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class FileReadingExample {
    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("example.txt"));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("Caught IOException: " + e.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                System.err.println("Failed to close the reader: " + e.getMessage());
            }
        }
    }
}
3.2. Xử Lý Nhiều Ngoại Lệ

Bạn có thể xử lý nhiều ngoại lệ khác nhau bằng cách sử dụng nhiều khối catch.

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class MultipleExceptionHandling {
    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("example.txt"));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            System.err.println("Caught FileNotFoundException: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("Caught IOException: " + e.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                System.err.println("Failed to close the reader: " + e.getMessage());
            }
        }
    }
}

4. Sử Dụng try-with-resources

Cấu trúc try-with-resources (giới thiệu từ Java 7) tự động đóng các tài nguyên khi kết thúc khối try. Điều này giúp mã nguồn gọn gàng hơn và giảm nguy cơ rò rỉ tài nguyên.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesExample {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("Caught IOException: " + e.getMessage());
        }
    }
}

5. Best Practices trong Xử Lý Ngoại Lệ

5.1. Bắt Các Ngoại Lệ Cụ Thể

Luôn bắt các ngoại lệ cụ thể thay vì bắt ngoại lệ chung chung (Exception). Điều này giúp mã nguồn rõ ràng và dễ bảo trì hơn.

try {
    // Khối mã có thể gây ra ngoại lệ
} catch (NullPointerException e) {
    // Xử lý NullPointerException
} catch (IOException e) {
    // Xử lý IOException
}
5.2. Ghi Log Ngoại Lệ

Ghi log ngoại lệ giúp bạn theo dõi và xử lý các vấn đề xảy ra trong ứng dụng một cách hiệu quả.

import java.util.logging.Logger;

public class LoggingExample {
    private static final Logger LOGGER = Logger.getLogger(LoggingExample.class.getName());

    public static void main(String[] args) {
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            LOGGER.severe("Caught ArithmeticException: " + e.getMessage());
        }
    }
}
5.3. Tái Ném Ngoại Lệ Nếu Cần Thiết

Trong một số trường hợp, bạn có thể cần tái ném ngoại lệ sau khi xử lý nó để lớp gọi có thể xử lý tiếp.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class RethrowExample {
    public static void main(String[] args) {
        try {
            processFile("example.txt");
        } catch (IOException e) {
            System.err.println("Handled IOException in main: " + e.getMessage());
        }
    }

    public static void processFile(String filePath) throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("Caught IOException: " + e.getMessage());
            throw e; // Tái ném ngoại lệ
        }
    }
}

6. Kết Luận

Cấu trúc try-catch-finally là một phần quan trọng trong việc xử lý ngoại lệ trong Java. Hiểu và sử dụng đúng cách cấu trúc này giúp bạn viết mã nguồn ổn định và dễ bảo trì hơn. Trong bài viết này, chúng ta đã tìm hiểu chi tiết về các phần của cấu trúc này, cung cấp các ví dụ thực tế và thảo luận về các best practices. Trong bài viết tiếp theo, chúng ta sẽ tiếp tục khám phá cách ném ngoại lệ và tạo các ngoại lệ tùy chỉnh.

More from this blog

devngu

169 posts