Java 8 - Biểu thức Lambda: Truy cập Biến bên ngoài

Truy cập Biến bên ngoài trong Biểu thức Lambda

Trong Java 8, biểu thức Lambda có khả năng truy cập các biến từ phạm vi bên ngoài. Tuy nhiên, không phải mọi biến bên ngoài đều có thể được Lambda truy cập. Chỉ những biến được khai báo là final hoặc thực sự không thể thay đổi (effectively final) mới có thể được tham chiếu trong biểu thức Lambda. Điều này có nghĩa là các biến cục bộ bên ngoài được tham chiếu trong biểu thức Lambda phải là final hoặc thực sự không thay đổi.

Quy tắc về Biến bên ngoài

  1. Không thể thay đổi (Immutability):
    • Biến phải là final hoặc thực sự không thể thay đổi.
    • Biến thực sự không thể thay đổi là những biến không được khai báo là final nhưng không bị sửa đổi trong biểu thức Lambda.
  2. Kiểm tra tính không thay đổi (Immutability Check):
    • Bộ biên dịch sẽ kiểm tra xem biến bên ngoài có bị sửa đổi trong biểu thức Lambda hay không.
    • Nếu cố gắng sửa đổi biến bên ngoài, bộ biên dịch sẽ báo lỗi.
  3. Phạm vi của biến cục bộ (Scope of Local Variables):
    • Biểu thức Lambda có thể truy cập các biến cục bộ từ phạm vi bên ngoài, nhưng các biến đó phải tuân thủ các quy tắc trên.
    • Các biến thành viên của lớp không bị giới hạn bởi quy tắc này và có thể được truy cập và sửa đổi tự do trong biểu thức Lambda.

Ví dụ mã nguồn

Dưới đây là một số ví dụ về cách biểu thức Lambda truy cập các biến bên ngoài.

Ví dụ 1: Sử dụng biến final

import java.util.Arrays;
import java.util.List;

public class LambdaBienBenNgoaiExample {

    public static void main(String[] args) {
        List<String> danhSachTen = Arrays.asList("Anna", "Ben", "Chloe", "David");

        final String chaoMung = "Xin chào: ";
        
        // Sử dụng biến final
        danhSachTen.forEach(ten -> System.out.println(chaoMung + ten));
    }
}

Trong ví dụ này, biến chaoMung được khai báo là final, do đó có thể được truy cập an toàn trong biểu thức Lambda.

Ví dụ 2: Sử dụng biến thực sự không thay đổi

import java.util.Arrays;
import java.util.List;

public class LambdaBienBenNgoaiExample {

    public static void main(String[] args) {
        List<String> danhSachTen = Arrays.asList("Anna", "Ben", "Chloe", "David");

        String chaoMung = "Xin chào: ";  // Không được khai báo là final
        
        // Sử dụng biến thực sự không thay đổi
        danhSachTen.forEach(ten -> System.out.println(chaoMung + ten));
    }
}

Trong ví dụ này, biến chaoMung mặc dù không được khai báo là final, nhưng không bị sửa đổi trong biểu thức Lambda, do đó bộ biên dịch cho phép.

Ví dụ 3: Thay đổi biến bên ngoài

import java.util.Arrays;
import java.util.List;

public class LambdaBienBenNgoaiExample {

    public static void main(String[] args) {
        List<String> danhSachTen = Arrays.asList("Anna", "Ben", "Chloe", "David");

        final String chaoMung = "Xin chào: ";

        // Cố gắng thay đổi biến bên ngoài
        danhSachTen.forEach(ten -> {
            chaoMung = "Chào bạn: ";  // Lỗi biên dịch
            System.out.println(chaoMung + ten);
        });
    }
}

Trong ví dụ này, việc cố gắng sửa đổi biến chaoMung bên trong biểu thức Lambda sẽ gây ra lỗi biên dịch vì chaoMungfinal.

Lưu ý

  • Nếu biến bên ngoài được khai báo là final, biểu thức Lambda có thể truy cập nó nhưng không thể sửa đổi.
  • Nếu biến bên ngoài không được khai báo là final nhưng không bị sửa đổi trong biểu thức Lambda, nó vẫn có thể được truy cập.
  • Nếu cố gắng sửa đổi biến bên ngoài trong biểu thức Lambda, dù biến đó không được khai báo là final, cũng sẽ gây ra lỗi biên dịch.

Biến thành viên của lớp

Đối với biến thành viên của lớp, quy tắc có phần khác biệt:

  • Biến thành viên:
    • Biến thành viên (trường) có thể được truy cập và sửa đổi tự do trong biểu thức Lambda, không bị giới hạn bởi final hoặc tính không thay đổi.
    • Điều này là vì biến thành viên được định nghĩa trong một thể hiện của lớp, chứ không phải trong phạm vi cục bộ.

Ví dụ 4: Sử dụng biến thành viên

import java.util.Arrays;
import java.util.List;

public class LambdaBienBenNgoaiExample {

    private String thongDiepChaoMung = "Xin chào: ";

    public static void main(String[] args) {
        List<String> danhSachTen = Arrays.asList("Anna", "Ben", "Chloe", "David");

        LambdaBienBenNgoaiExample viDu = new LambdaBienBenNgoaiExample();

        // Sử dụng biến thành viên
        danhSachTen.forEach(ten -> System.out.println(viDu.thongDiepChaoMung + ten));
    }
}

Trong ví dụ này, thongDiepChaoMung là một biến thành viên của lớp, do đó có thể được truy cập tự do trong biểu thức Lambda.

Thẻ: Java Java 8 Lambda Biến hiệu quả cuối cùng

Đăng vào ngày 5 tháng 6 lúc 17:25