Java 8 mang đến một loại kiểu dữ liệu mới: Optional có tính năng tương tự với những ngôn ngữ khác. Bài viết này sẽ đưa ra những cân nhắc cho bạn cách sử dụng nó đúng với mục đích mà nó được tạo ra.
Optional là một kiểu dữ liệu container, nó bao bọc chỉ một giá trị duy nhất nếu giá trị đó tồn tại. Như vậy mục đích của nó đưa ra là về sự tồn tại của dữ liệu hay không. Ví dụ với method này:
public Optional<Customer> findCustomerWithSSN(String ssn) {
...
}
Phương thức này trả về một Optional đồng nghĩa với có thể sẽ không có customer nào tương ứng với parameter social sercurity number.
Nó thông qua System để nhắc nhở và ép buộc nơi gọi (caller) phương thức này phải xử lý vấn đề không có customer tương ứng với SSN. Và caller có thể xử lý như sau:
Optional<Customer> optional = findCustomerWithSSN(ssn);
if (optional.isPresent()) {
Customer customer = maybeCustomer.get();
... use customer ...
} else {
... deal with absence case ...
}
Hoặc đưa ra một giá trị default:
Long value = findOptionalLong(ssn).orElse(0L);
Cách sử dụng optional như thế này nó tương tự như cách chúng ta xử lý exception. Bằng cách bắn ra một checked exception, chúng ta ép caller phải đưa ra cách xử lý cho tình huống ngoại lệ.
Optional đưa ra với mục đích làm giảm NullPointerException bằng cách thêm vào một API tiện lợi đại diện cho việc trả về một dữ liệu có thể null.
Nếu Optional được sinh ra từ sớm hơn, hầu hết các thư viện và ứng dụng có thể xử lý tốt hơn vấn đề null pointer tương đương với ít bugs sản sinh hơn.
Làm sao để sử dụng Optional?
Optional nên được sử dụng như một giá trị trả về của một phương thức nào đấy mà không thể chắc chắn dữ liệu trả về không null. Trích dẫn này nằm trong OpenJDK mailing list:
JSR-335 có cảm giác nhấn mạnh rằng Optional không nên trở thành một thứ gì đó vượt quá định nghĩa đơn giản: optional-return. Có một số người thậm chí còn gợi í nên đổi tên Optional thành OptionalReturn để nó thể hiện đúng ý nghĩa.
Trong ngữ cảnh của Domain Driven Development, Optional chỉ nên được sử dụng như giá trị trả về của các service, repository hay utility method.
Optional không sinh ra để bọc tất cả các giá trị nào có thể null. Input parameter bắt buộc phải được kiểm tra xem có null hay không.
Giống như lúc sử dụng null, Optional không hoàn toàn mang ý nghĩa giá trị tồn tại hay không. Cũng giống như null nó có thể đại diện cho nhiều ý nghĩa(vd giá trị không tìm được, ...).
Caller của method nào đó vẫn phải check trong javadoc để hiểu ý nghĩa của Optional trả về nếu muốn sử dụng nó một cách chính xác.
Cũng giống như việc cho checked exception bị bắt và thực thi tiếp bên trong một empty block, không có gì áp đặt caller chỉ gọi get() và không làm gì cả.
Điều gì không ổn khi trả về null?
Vấn đề sảy ra khi caller có thể không đọc javadoc của method đó và quên đi việc giá trị trả về có thể bị null. Điều này sảy ra cực kỳ thường xuyên và nó là lỗi chính gây ra NullPointerException.
Optional không nên sử dụng khi nào?
Optional không giúp ích được gì trong những hoàn cảnh sau:
-Bên trong một domain model layer (not serializable) bởi vì Optional không phải là serializable
- Trong DTOs (cùng lý do bên trên)
- Input parameter method
- Constructor parameter
Optional giúp được gì functional programming style của Java 8?
Trong dây chuyền các function, Optional cung cấp ifPresent() cũng cho phép bạn đưa nó vào trong dây chuyền:
findCustomerWithSSN(ssn).ifPresent(() ->
System.out.println("customer exists!"));
Xem thêm Java là gì?
Unpublished comment
Viết câu trả lời