Trong Java, phương thức finalize() là một phương thức được định nghĩa trong lớp java.lang.Object, và nó được gọi trước khi một đối tượng bị thu hồi bởi Garbage Collector (GC). Mục đích của phương thức này là để thực hiện các thao tác dọn dẹp cần thiết trước khi đối tượng không còn sử dụng nữa. Bài viết này sẽ đi vào chi tiết về phương thức finalize(), cách hoạt động của nó, và một số khuyến nghị khi sử dụng.

1. Khái niệm về phương thức finalize()

1.1. Định nghĩa

  • Phương thức finalize() được sử dụng để thực hiện các thao tác dọn dẹp trước khi một đối tượng bị thu hồi. Nó được gọi tự động bởi Garbage Collector khi không còn tham chiếu nào đến đối tượng đó.

1.2. Cú pháp

protected void finalize() throws Throwable {
    // Thực hiện các thao tác dọn dẹp
    super.finalize(); // Gọi phương thức finalize() của lớp cha
}

2. Cách hoạt động của finalize()

2.1. Khi nào phương thức finalize() được gọi

  • Phương thức finalize() sẽ được gọi trước khi Garbage Collector thu hồi bộ nhớ của một đối tượng. Điều này thường xảy ra khi không còn bất kỳ tham chiếu nào đến đối tượng đó.

2.2. Quy trình gọi

  • Garbage Collector xác định đối tượng nào có thể thu hồi và sau đó gọi phương thức finalize() (nếu có) trước khi giải phóng bộ nhớ.

2.3. Sự không chắc chắn

  • Việc gọi phương thức finalize() không chắc chắn về thời gian. Điều này có nghĩa là không có đảm bảo khi nào hoặc nếu nó sẽ được gọi. Vì vậy, bạn không nên dựa vào nó để giải phóng tài nguyên quan trọng.

3. Ví dụ sử dụng finalize()

class MyClass {
    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println("Dọn dẹp tài nguyên trước khi đối tượng bị thu hồi.");
            // Dọn dẹp tài nguyên như đóng file, kết nối database, v.v.
        } finally {
            super.finalize(); // Gọi phương thức finalize() của lớp cha
        }
    }
}

public class FinalizeExample {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj = null; // Gỡ bỏ tham chiếu đến đối tượng
        System.gc(); // Yêu cầu Garbage Collector chạy
    }
}

Lưu ý: Trong ví dụ trên, khi System.gc() được gọi, Garbage Collector sẽ cố gắng thu hồi bộ nhớ và sẽ gọi phương thức finalize() của đối tượng obj trước khi nó bị thu hồi.

4. Khuyến nghị khi sử dụng finalize()

4.1. Không nên dựa vào finalize()

  • Không nên dựa vào phương thức finalize() để giải phóng tài nguyên quan trọng như kết nối cơ sở dữ liệu, tệp, hoặc bất kỳ tài nguyên nào cần thiết cho ứng dụng của bạn.

4.2. Sử dụng try-with-resources

  • Thay vì sử dụng finalize(), bạn nên sử dụng cấu trúc try-with-resources trong Java 7 và các phiên bản cao hơn để tự động đóng tài nguyên.
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    // Đọc dữ liệu từ file
} catch (IOException e) {
    e.printStackTrace();
}

4.3. Đã bị loại bỏ trong Java 9

  • Kể từ Java 9, phương thức finalize() đã bị đánh dấu là deprecated và sẽ bị loại bỏ trong các phiên bản sau. Thay vào đó, Java khuyến nghị sử dụng java.lang.ref.Cleaner để thực hiện các tác vụ dọn dẹp.

5. Kết luận

Phương thức finalize() trong Java được sử dụng để thực hiện các thao tác dọn dẹp trước khi một đối tượng bị thu hồi. Tuy nhiên, việc sử dụng finalize() không được khuyến khích do không chắc chắn về thời gian gọi, và nó có thể dẫn đến việc tiêu tốn tài nguyên không cần thiết. Thay vào đó, các kỹ thuật như try-with-resources hoặc java.lang.ref.Cleaner nên được sử dụng để quản lý tài nguyên một cách hiệu quả.