2017-05-13 19 views
5

Tôi đang tái cấu trúc mã thành Java 8 và tôi muốn thay thế kiểm tra null bằng Tùy chọn.java 8 tùy chọn để thay thế trả về null

public Employee findEmployeeById(String id) { 
    List<Employee> empList = .. //some db query 
    return (empList.isEmpty() ? null : empList.get(0)); 
} 

Optional.ofNullable(empList.get(0)) sẽ không hoạt động khi nó sẽ ném IndexOutofBoundException

Hoặc nên tôi lý tưởng thay thế null với Optional.empty()?

+0

Tại sao truy vấn của bạn chỉ trả về một kết quả duy nhất ở địa điểm đầu tiên? – Marvin

+0

Đó là một logic phức tạp .... của gia nhập trái và tất cả .... Tôi hiểu bạn điểm nhưng không thể thực sự thay đổi rằng – coder25

+6

'return empList.isEmpty()? Optional.empty(): Optional.of (empList.get (0)); ' – Jesper

Trả lời

9

Như @Jesper đã được đề cập trong các nhận xét, bạn phải kiểm tra xem danh sách có trống không và sau đó trả về một trống Optional.

public Optional<Employee> findEmployeeById(String id) { 
    List<Employee> empList = .. //some db query 
    return empList.isEmpty() ? Optional.empty() : Optional.of(empList.get(0)); 
} 

Một Optional là một wrapper quanh một giá trị tiềm năng null cho phép bạn để tránh kiểm tra một cách rõ ràng cho null khi bạn sử dụng nó.

Hãy xem Optional documentation để xem chức năng nào cung cấp.

Ví dụ, bạn có thể nhận được tên của một nhân viên hoặc "không rõ" nếu nó vắng mặt, mà không kiểm tra cho null:

Optional<Employee> emp = findEmployeeById(id); 
String name = emp.map(Employee::getName).orElse("unknown"); 

Bạn có thể đọc this post about Uses for Optional để xem nếu nó làm cho tinh thần để bạn có thể sử dụng Optional.

3

Tại sao bạn không chỉ đơn giản là thay thế phương pháp của bạn với:

public Optional<Employee> findEmployeeById(String id) { 
    List<Employee> empList = .. //some db query 
    return (empList.isEmpty() ? Optional.empty() : 
       Optional.ofNullable(empList.get(0))); 
} 

tôi đề nghị bạn quấn empList.get(0) trong một Optional.ofNullable trong trường hợp nó vẫn có thể được null.

Theo như lý do tại sao tốt hơn: hãy suy nghĩ về người gọi của phương pháp. Ai đó đang gọi phương pháp của bạn phải suy nghĩ những gì thực sự làm khi kết quả là empty.

Bên cạnh đó tại buộc bạn vào viết code như:

Optional<Employee> emp = findEmployeeById("12"); 

if (emp.isPresent()) { 

} else { 
    .... 
} 

Bạn cũng có thể chuỗi này để trở thành thạo hơn như:

emp.orElseThrow(RuntimeException::new) 

Hoặc phương pháp bắt buộc khác.

Đó không phải chỉ đơn giản là trường hợp khi bạn trả lại Nhân viên. Bạn thậm chí không nghĩ (thường) để kiểm tra nếu tham chiếu là null.

Điều đó làm cho mã của bạn ít bị lỗi và dễ hiểu hơn.

2

Một khả năng khác sẽ làm điều đó như sau:

return Optional.of(empList).filter(list -> !list.isEmpty()).map(list -> list.get(0)); 

này sẽ tự động trả về một sản phẩm nào Optional trong trường hợp danh sách là rỗng hoặc empList.get(0) lợi nhuận null.

Nếu empList có thể là null, hãy cân nhắc sử dụng Optional.ofNullable(empList) thay vì Optional(empList).

5

Với tôi giải pháp tự nhiên là giữ cấu trúc ? : như trong Floern’s answer. Tuy nhiên, nếu bạn muốn thoát khỏi điều đó, đó cũng là một giải pháp thanh lịch mà không có nó:

public Optional<Employee> findEmployeeById(String id) { 
    List<Employee> empList = .. //some db query 
    return empList.stream().findFirst(); 
} 

này mang đến cho bạn những gì bạn muốn vì findFirst() trả về một Optional. Nếu bạn không quan tâm đến yếu tố nào bạn nhận được - hoặc bạn biết không bao giờ có nhiều yếu tố - bạn có thể sử dụng cách khác findAny(), nó cũng trả về một số Optional.

+0

Tốt nhất, không nghĩ về điều đó – Floern

+2

Tốt đẹp! Bạn thậm chí không cần địa chỉ 'empList', do đó, điều này có thể được giảm xuống' return someDbQuery(). Stream(). FindFirst() '. –

Các vấn đề liên quan