Trong Java, final, finalizefinally là ba khái niệm khác nhau nhưng thường dễ gây nhầm lẫn do cách đặt tên tương tự. Bài viết này sẽ giúp bạn hiểu rõ sự khác biệt giữa chúng, cách sử dụng và vai trò của từng khái niệm trong lập trình Java.

1. final

final là một từ khóa được sử dụng để xác định một giá trị không thể thay đổi trong Java. Khi một biến, phương thức hoặc lớp được đánh dấu là final, điều này có nghĩa là nó không thể được sửa đổi hoặc ghi đè sau khi được khởi tạo.

1.1. final với biến

Khi một biến được khai báo là final, bạn chỉ có thể gán giá trị cho nó một lần. Sau khi gán giá trị, nếu bạn cố gắng thay đổi giá trị của biến đó, trình biên dịch sẽ báo lỗi.

final int number = 10;
number = 20; // Lỗi biên dịch: không thể gán lại giá trị cho biến final

1.2. final với phương thức

Nếu một phương thức được khai báo là final, nó không thể bị ghi đè (overridden) trong các lớp con.

class Animal {
    final void makeSound() {
        System.out.println("Animal makes sound");
    }
}

class Dog extends Animal {
    void makeSound() { // Lỗi biên dịch: không thể ghi đè phương thức final
        System.out.println("Woof");
    }
}

1.3. final với lớp

Khi một lớp được khai báo là final, nó không thể được kế thừa (inherited) bởi bất kỳ lớp nào khác.

final class FinalClass {
    // Nội dung của lớp
}

class SubClass extends FinalClass { // Lỗi biên dịch: không thể kế thừa lớp final
}

2. finalize

finalize là một phương thức trong lớp Object, được gọi bởi Garbage Collector (GC) trước khi một đối tượng bị thu hồi (garbage collected). Mục đích của phương thức này là để thực hiện các hành động dọn dẹp (cleanup) như đóng tệp, giải phóng tài nguyên, hoặc lưu trạng thái của đối tượng.

2.1. Cách sử dụng finalize

Phương thức finalize có thể được ghi đè trong lớp của bạn để thực hiện các hành động 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 trong các phiên bản Java hiện tại do các vấn đề về hiệu suất và độ không chắc chắn về thời gian thực hiện.

class MyClass {
    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println("Cleaning up resources");
        } finally {
            super.finalize();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj = null; // Đánh dấu obj cho Garbage Collector
        System.gc(); // Yêu cầu Garbage Collector thu hồi
    }
}

3. finally

finally là một từ khóa được sử dụng trong khối xử lý ngoại lệ (exception handling) để đảm bảo rằng một khối mã sẽ được thực thi, bất kể ngoại lệ có xảy ra hay không. Khối finally thường đi kèm với trycatch.

3.1. Cách sử dụng finally

Khối finally được sử dụng để thực hiện các hành động dọn dẹp như đóng tệp, giải phóng tài nguyên hoặc thực hiện bất kỳ mã nào cần thiết sau khi xử lý ngoại lệ.

public class Main {
    public static void main(String[] args) {
        try {
            int result = 10 / 0; // Gây ra ngoại lệ
        } catch (ArithmeticException e) {
            System.out.println("Division by zero error");
        } finally {
            System.out.println("This block always executes");
        }
    }
}

Tóm tắt sự khác biệt

Khái niệmMô tả
finalTừ khóa dùng để khai báo biến, phương thức, hoặc lớp không thể thay đổi (không thể gán lại, ghi đè, hoặc kế thừa).
finalizePhương thức trong lớp Object được gọi trước khi một đối tượng bị thu hồi để thực hiện các hành động dọn dẹp.
finallyTừ khóa được sử dụng trong khối xử lý ngoại lệ để đảm bảo mã trong khối finally luôn được thực thi, bất kể có xảy ra ngoại lệ hay không.

Tóm lại, final, finalize, và finally là ba khái niệm khác nhau trong Java với các vai trò và mục đích riêng. Hiểu rõ sự khác biệt giữa chúng sẽ giúp bạn viết mã hiệu quả và tránh những lỗi không mong muốn trong quá trình phát triển ứng dụng.