2014-10-12 20 views
182

Optional loại được giới thiệu trong Java 8 là một điều mới cho nhiều nhà phát triển.Nên Java 8 getters trở về loại tùy chọn?

Phương thức getter có trả lại Optional<Foo> thay cho kiểu cổ điển Foo một phương pháp hay không? Giả sử rằng giá trị có thể là null.

+7

Mặc dù điều này có khả năng thu hút các câu trả lời có ý kiến, nhưng đây là một câu hỏi hay. Tôi đang mong chờ một câu trả lời với các sự kiện thực tế về chủ đề này. – Justin

+7

Câu hỏi đặt ra là liệu sự vô dụng là không thể tránh khỏi. Một thành phần có thể có một thuộc tính được cho phép là null, nhưng vẫn còn, lập trình viên sử dụng thành phần đó có thể quyết định nghiêm chỉnh giữ thuộc tính đó là 'không'. Vì vậy, lập trình viên không cần phải xử lý 'Tùy chọn' sau đó. Hoặc, nói cách khác, không 'null' thực sự đại diện cho sự vắng mặt của một giá trị giống như kết quả tìm kiếm (trong đó' Tùy chọn' là thích hợp) hoặc là 'null' chỉ là một thành viên của tập các giá trị có thể. – Holger

+0

Xem thêm phần thảo luận về chú thích '@ NotNull': https://stackoverflow.com/q/4963300/873282 – koppor

Trả lời

303

Tất nhiên, mọi người sẽ làm những gì họ muốn. Nhưng chúng tôi đã có ý định rõ ràng khi thêm tính năng này và nó là không phải là là một mục đích chung Có thể hoặc một số loại, nhiều như mọi người muốn chúng tôi làm như vậy. Mục đích của chúng tôi là cung cấp một cơ chế hạn chế cho các kiểu trả về phương thức thư viện khi cần có cách rõ ràng để đại diện cho "không có kết quả" và sử dụng null vì vậy có khả năng gây ra lỗi.

Ví dụ: có thể bạn không bao giờ nên sử dụng nó cho thứ gì đó trả về một loạt kết quả hoặc danh sách kết quả; thay vào đó trả về một mảng hoặc danh sách trống. Bạn hầu như không bao giờ nên sử dụng nó như là một lĩnh vực của một cái gì đó hoặc một tham số phương pháp.

Tôi nghĩ rằng thường xuyên sử dụng nó như là một giá trị trả lại cho getters chắc chắn sẽ được sử dụng quá mức.

Không có gì sai với tùy chọn cần tránh, nó không phải là điều mà nhiều người mong muốn, và chúng tôi khá lo ngại về nguy cơ quá nhiệt tình.

(thông báo dịch vụ công cộng:. KHÔNG BAO GIỜ gọi Optional.get trừ khi bạn có thể chứng minh điều đó sẽ không bao giờ được null, thay vào đó sử dụng một trong những phương pháp an toàn như orElse hoặc ifPresent Nhìn lại, chúng ta nên đã kêu gọi get cái gì đó như getOrElseThrowNoSuchElementException hoặc cái gì đó làm cho nó rõ ràng hơn rằng đây là một phương pháp rất nguy hiểm làm suy yếu toàn bộ mục đích của Optional ở nơi đầu tiên.)

+17

(Về phần cuối)… và khi chúng tôi tự tin, giá trị không bao giờ là 'null' chúng ta có thể sử dụng' orElseThrow (AssertionError :: new) ', ahem hoặc' orElseThrow (NullPointerException :: new) '… – Holger

+13

Bạn sẽ làm gì đã thực hiện một cách khác nhau nếu ý định của bạn * đã * được giới thiệu một mục đích chung có thể hoặc một số loại? Có cách nào trong đó Tùy chọn không phù hợp với hóa đơn cho một, hoặc là nó chỉ là giới thiệu Optionals trên một API mới sẽ làm cho nó không Java-ish? –

+12

Theo "loại mục đích chung", tôi có nghĩa là xây dựng nó vào hệ thống kiểu ngôn ngữ, thay vì cung cấp một lớp thư viện gần đúng. (Một số ngôn ngữ có loại T? (T hoặc null) và T! (Không có giá trị T)) Tùy chọn chỉ là một lớp; chúng tôi không thể thực hiện chuyển đổi tiềm ẩn giữa Foo và Tùy chọn như chúng tôi có thể có với hỗ trợ ngôn ngữ. –

11

Tôi muốn nói chung một ý tưởng hay là sử dụng loại tùy chọn cho các giá trị trả về có thể rỗng. Tuy nhiên, w.r.t. vào các khung công tác, tôi cho rằng việc thay thế các getters cổ điển bằng các kiểu tùy chọn sẽ gây ra nhiều rắc rối khi làm việc với các khung công tác (ví dụ, Hibernate) dựa trên các quy ước mã hóa cho các getters và setters.

+7

Lời khuyên này chính xác là điều tôi muốn nói" chúng tôi lo ngại về nguy cơ lạm dụng nhiệt tình "trong http : //stackoverflow.com/a/26328555/3553087. –

51

Sau khi thực hiện một ít nghiên cứu của riêng tôi, tôi đã gặp một số điều có thể gợi ý khi điều này là phù hợp. Các thẩm quyền nhất là đoạn trích sau đây từ một bài báo Oracle:

"It is important to note that the intention of the Optional class is not to replace every single null reference. Instead, its purpose is to help design more-comprehensible APIs so that by just reading the signature of a method, you can tell whether you can expect an optional value. This forces you to actively unwrap an Optional to deal with the absence of a value." - Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional!

Tôi cũng thấy đoạn trích này từ Java 8 Optional: How to use it

"Optional is not meant to be used in these contexts, as it won't buy us anything:

  • in the domain model layer (not serializable)
  • in DTOs (same reason)
  • in input parameters of methods
  • in constructor parameters"

nào cũng dường như để nâng cao một số điểm hợp lệ.

Tôi không thể tìm thấy bất kỳ ý nghĩa tiêu cực hoặc cờ đỏ nào để đề xuất rằng Optional nên tránh. Tôi nghĩ ý tưởng chung là, nếu nó hữu ích hoặc cải thiện khả năng sử dụng của API của bạn, hãy sử dụng nó.

+4

http://stackoverflow.com/questions/25693309/ - có vẻ như Jackson đã hỗ trợ nó, vì vậy "không serializable" không còn là một lý do hợp lệ nữa :) – Vlasec

+1

Tôi đề nghị bạn có địa chỉ trả lời tại sao sử dụng 'Optional' trong tham số đầu vào các phương thức (cụ thể hơn các nhà xây dựng) "sẽ không mua cho chúng tôi bất cứ thứ gì". http://dolszewski.com/java/java-8-optional-use-cases/ chứa một lời giải thích tốt đẹp. – Gili

+0

Tôi nhận thấy rằng các kết quả tùy chọn cần phải được chuyển đổi thành các API khác yêu cầu tham số Tùy chọn. Kết quả là một API khá dễ hiểu. Xem http://stackoverflow.com/a/31923105/105870 –

1

Nếu bạn đang sử dụng serializers hiện đại và các khuôn khổ khác mà hiểu Optional sau đó tôi đã tìm thấy những hướng dẫn làm việc tốt khi viết Entity đậu và các lớp miền:

  1. Nếu lớp serialization (thường là một DB) cho phép một giá trị null cho một ô trong cột BAR trong bảng FOO, thì getter Foo.getBar() có thể trả về Optional cho biết nhà phát triển rằng giá trị này có thể được dự kiến ​​là rỗng và họ nên andle này. Nếu DB đảm bảo giá trị sẽ không được null thì getter nên không bọc nó trong một Optional.
  2. Foo.bar phải là privatekhôngOptional. Có thực sự không có lý do cho nó là Optional nếu nó là private.
  3. Bộ thiết lập Foo.setBar(String bar) phải có loại barkhôngOptional. Nếu có thể sử dụng đối số null thì hãy nêu điều này trong nhận xét JavaDoc. Nếu không được sử dụng null một IllegalArgumentException hoặc một số logic kinh doanh phù hợp, IMHO, phù hợp hơn.
  4. Nhà xây dựng không cần Optional đối số (vì các lý do tương tự như điểm 3). Nói chung tôi chỉ bao gồm các đối số trong hàm dựng là phải là không null trong cơ sở dữ liệu tuần tự hóa.

Để thực hiện trên hiệu quả hơn, bạn có thể muốn chỉnh sửa mẫu IDE của bạn để tạo ra thu khí và các mẫu tương ứng cho toString(), equals(Obj o) vv hoặc sử dụng các trường trực tiếp cho những người (hầu hết các máy phát điện IDE đã đối phó với null).

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