Khi nào nên sử dụng giá trị null của Boolean?


159

Java booleancho phép giá trị của truefalsetrong khi Boolean cho phép true, falsenull. Tôi đã bắt đầu chuyển đổi booleans của tôi thành Booleans. Điều này có thể gây ra sự cố trong các thử nghiệm như

Boolean set = null;
...
if (set) ...

trong khi kiểm tra

if (set != null && set) ...

có vẻ dễ bị lỗi và dễ bị lỗi

Khi nào, nếu có, sử dụng Booleans với các giá trị null có hữu ích không? Nếu không bao giờ, thì những lợi thế chính của đối tượng được bọc là gì?

CẬP NHẬT: Đã có rất nhiều câu trả lời có giá trị mà tôi đã tóm tắt một số câu trả lời trong câu trả lời của riêng tôi. Tôi tốt nhất là một trung gian trong Java vì vậy tôi đã cố gắng thể hiện những điều mà tôi thấy hữu ích. Lưu ý rằng câu hỏi là "cụm từ không chính xác" (Boolean không thể "có giá trị null") nhưng tôi đã để lại nó trong trường hợp những người khác có cùng quan niệm sai lầm


7
Đôi khi, bạn muốn một trạng thái chưa được khởi tạo và thiết lập Booleanbiến để nulltrợ giúp.
nhahtdh

2
"Luôn luôn" là một chút mạnh mẽ mà tôi không dám xác nhận, nhưng tôi sẽ mong đợi một thử nghiệm nullnếu nó thực sự được sử dụng như là trạng thái thứ 3.
nhahtdh

6
Bạn có lý do để chuyển đổi booleans thành Booleans không? Tôi sẽ sử dụng kiểu nguyên thủy và chỉ bọc nó nếu có lý do chính đáng để làm như vậy, ví dụ khi tôi cần chuyển một biến bằng tham chiếu.
JPE

7
Bạn cũng có thể muốn kiểm tra này: thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
biziclop

6
Không có thứ gọi là "giá trị null trong Boolean". A Booleanlà một đối tượng, trong khi a booleanlà "vô hướng". Nếu một Booleantham chiếu được đặt thành null, điều đó có nghĩa là Booleanđối tượng tương ứng không tồn tại. Bạn không thể đặt bất cứ thứ gì bên trong thứ gì đó không tồn tại.
Licks nóng

Câu trả lời:


244

Sử dụng booleanhơn là Booleanmọi lúc bạn có thể. Điều này sẽ tránh nhiều NullPointerExceptions và làm cho mã của bạn mạnh mẽ hơn.

Boolean là hữu ích, ví dụ

  • để lưu trữ booleans trong bộ sưu tập (Danh sách, Bản đồ, v.v.)
  • để đại diện cho một boolean nullable (ví dụ đến từ một cột boolean nullable trong cơ sở dữ liệu). Giá trị null có thể có nghĩa là "chúng tôi không biết là đúng hay sai" trong ngữ cảnh này.
  • mỗi lần một phương thức cần một đối tượng làm đối số và bạn cần truyền một giá trị boolean. Ví dụ, khi sử dụng sự phản chiếu hoặc phương pháp như thế nào MessageFormat.format().

35
Giá trị null trong cơ sở dữ liệu cũng có thể có nghĩa là "FileNotFound"
Karl Johan

31
Viên đạn thứ hai của bạn thực sự là cốt lõi của câu trả lời đúng cho câu hỏi này, tôi nghĩ vậy.
Niels Brinch

3
Một cách sử dụng khác cho Boolean mà tôi đã có là tham số loại chung khi mở rộng các lớp chung - liên quan chặt chẽ đến điểm 3.
Alex

6
Quá tải khái niệm null với ý nghĩa khác với "vũ trụ không biết" nó yếu hơn so với việc sử dụng enum có giá trị 3 (hoặc nhiều hơn). Làm cho việc đọc mã truyền tham số vào phương thức rõ ràng hơn, quá.
bluevector

16
Hoặc # 4: Boolean isSchrodinger‎CatAlive = null;(xin lỗi, không thể cưỡng lại;)).
Matthieu

58

Tôi gần như không bao giờ sử dụng Booleanvì ngữ nghĩa của nó là mơ hồ và tối nghĩa. Về cơ bản bạn có logic 3 trạng thái: đúng, sai hoặc không biết. Đôi khi sử dụng nó rất hữu ích khi ví dụ: bạn đã cho người dùng lựa chọn giữa hai giá trị và người dùng hoàn toàn không trả lời và bạn thực sự muốn biết thông tin đó (nghĩ: cột cơ sở dữ liệu NULLable).

Tôi thấy không có lý do để chuyển đổi từ boolean sang Booleanvì nó giới thiệu thêm chi phí bộ nhớ, khả năng NPE và ít gõ hơn. Thông thường tôi sử dụng vụng về BooleanUtils.isTrue()để làm cho cuộc sống của tôi dễ dàng hơn một chút với Boolean.

Lý do duy nhất cho sự tồn tại của Booleanlà khả năng có các bộ sưu tập Booleanloại (thuốc generic không cho phép boolean, cũng như tất cả các nguyên thủy khác).


1
Tuy nhiên, đây là một thư viện bên ngoài (Apache commons).
nhahtdh

4
Đối với logic đa trị, tốt hơn là sử dụng enums. Do đó, Boolean nên để các biến đấm bốc (tự động) để sử dụng trong các cấu trúc dữ liệu.
JPE

39
Khi sử dụng Boolean, một thử nghiệm thuận tiện để tránh ngoại lệ con trỏ null là Boolean.TRUE.equals(myBooleanObject)hoặc Boolean.FALSE.equals(myBooleanObject).
Christopher Peisert

10
Một đối tượng Boolean chỉ có hai trạng thái - truefalse. nullkhông một nhà nước của đối tượng, mà là một trạng thái của đối tượng tham chiếu.
Licks nóng

2
Để lại cho apache commons giống như "Ai đó có thể làm hỏng việc đánh giá các booleans ... hãy tạo ra một isTrue()phương pháp ..." nghe có vẻ như là thứ đáng sợ nhất trong lịch sử các chức năng tiện ích. Tuy nhiên, bằng cách nào đó, nó hữu ích ... đó là wtf lớn nhất ở đây.
corsiKa

33

Wow, những gì trên trái đất? Có phải chỉ có tôi hoặc tất cả những câu trả lời sai hoặc ít nhất là sai lệch?

Lớp Boolean là một lớp bao quanh kiểu nguyên thủy boolean. Việc sử dụng trình bao bọc này là để có thể vượt qua một boolean trong một phương thức chấp nhận một đối tượng hoặc chung chung. Tức là véc tơ.

Một đối tượng Boolean KHÔNG BAO GIỜ có giá trị null. Nếu tham chiếu của bạn đến Boolean là null, điều đó chỉ có nghĩa là Boolean của bạn chưa bao giờ được tạo.

Bạn có thể thấy điều này hữu ích: http://grepcode.com/file/reposective.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Boolean.java

Một tham chiếu Boolean null chỉ nên được sử dụng để kích hoạt logic tương tự mà bạn có bất kỳ tham chiếu null nào khác. Sử dụng nó cho ba trạng thái logic là vụng về.

EDIT: thông báo, đó Boolean a = true;là một tuyên bố sai lệch. Điều này thực sự tương đương với một cái gì đó gần hơn Boolean a = new Boolean(true); Xin vui lòng xem autoboxing ở đây: http://en.wikipedia.org/wiki/Boxing_%28computer_science%29#Autoboxing

Có lẽ đây là nơi mà nhiều sự nhầm lẫn đến từ.

EDIT2: Vui lòng đọc bình luận bên dưới. Nếu bất cứ ai có ý tưởng về cách cấu trúc lại câu trả lời của tôi để kết hợp điều này, xin vui lòng làm như vậy.


2
Tôi không hiểu câu nói của bạn "Boolean KHÔNG BAO GIỜ có giá trị null". Tôi có thể tạo Boolean ( Boolean a = true;) và sau đó đặt thành null ( a = null;). Nó có thể không thanh lịch hoặc khôn ngoan, nhưng nó có thể.
peter.m bồ.rust

7
Khi bạn làm Boolean a; a là một con trỏ tới một đối tượng Boolean. Nếu bạn a = null;chưa đặt Boolean thành null, bạn đã đặt tham chiếu của mình thành null. Làm Boolean a = null; a.booleanValue();trong trường hợp này, bạn thậm chí không bao giờ tạo một đối tượng Boolean và do đó nó sẽ đưa ra một nhận thức nullpulumexception. Hãy cho tôi biết nếu bạn cần hướng dẫn thêm.
dùng606723

Hơn nữa, khi bạn làm Boolean a = true;, Nó thực hiện một số loại phép thuật thực sự được hiểu là Boolean a = new Boolean(true);Thats có thể không hoàn toàn chính xác vì lý do hiệu suất, nhưng bạn phải nhận ra rằng Boolean vẫn là một đối tượng.
dùng606723

7
@missingno, Tất cả các mã liên quan đến bất kỳ đối tượng nào đều phải xử lý vấn đề này. Một tham chiếu đối tượng có thể là null hoặc không. Đây không phải là trường hợp đặc biệt và không cần xem xét đặc biệt.
dùng606723

3
Bạn đang thiếu quan điểm của tôi @missingno. Tôi đồng ý rằng chúng ta cần xem xét các giá trị tham chiếu null. Tôi đã không bao giờ tranh luận chống lại điều đó. Nhưng chúng ta cần phải làm điều này cho MỌI THAM KHẢO. Một tài liệu tham khảo Boolean null không phải là trường hợp đặc biệt. Và do đó, giá trị tham chiếu Boolean null không yêu cầu xem xét đặc biệt.
dùng606723

24

Có ba lý do nhanh chóng:

  • để biểu diễn các giá trị boolean của Cơ sở dữ liệu, có thể true, falsehoặcnull
  • để biểu thị các xsd:booleangiá trị của Lược đồ XML được khai báo vớixsd:nillable="true"
  • để có thể sử dụng các loại chung chung: List<Boolean>- bạn không thể sử dụngList<boolean>

Tôi đã viết rõ ràng "boolean", không phải " boolean" (kiểu dáng tâm trí), bởi vì trong Oracle bạn thường sử dụng char(1) nullvới các giá trị 'T' và 'F'. Vì vậy, nó có thể (ví dụ: bộ điều hợp loại Hibernate) là null :)
Grzegorz Grzybek

2
Cơ sở dữ liệu nào không cho phép null cho boolean? Nếu bạn đặt cột thành nullable, kiểu dữ liệu sẽ không còn quan trọng nữa ...
Michal B.

@MichalB. Kiểu bit Sybase (và SQL Server) infocenter.sybase.com/help/index.jsp?topic=/ mẹo
mmmmmm

@Mark - không, SQL Server không cho phép một bit nullable - msdn.microsoft.com/en-us/l Library / ms177603.aspx
David M

11

TRẢ LỜI CÂU HỎI RIÊNG: Tôi nghĩ sẽ rất hữu ích khi trả lời câu hỏi của chính mình vì tôi đã học được rất nhiều từ các câu trả lời. Câu trả lời này nhằm giúp những người - như tôi - những người không có sự hiểu biết đầy đủ về các vấn đề. Nếu tôi sử dụng ngôn ngữ không chính xác xin vui lòng sửa cho tôi.

  • "Giá trị" null không phải là một giá trị và về cơ bản khác với truefalse. Đó là sự vắng mặt của một con trỏ đến các đối tượng. Do đó, nghĩ rằng Boolean có giá trị 3 là sai về cơ bản
  • Cú pháp cho Boolean được viết tắt và che giấu thực tế là các tham chiếu trỏ đến các Đối tượng:

    Boolean a = true;

che giấu sự thật đó truelà một đối tượng. Các bài tập tương đương khác có thể là:

Boolean a = Boolean.TRUE;

hoặc là

Boolean a = new Boolean(true);
  • Cú pháp viết tắt

    if (a) ...

khác với hầu hết các bài tập khác và che giấu sự thật rằng có thể là một tham chiếu đối tượng hoặc nguyên thủy. Nếu một đối tượng cần phải kiểm tra nullđể tránh NPE. Đối với tôi, việc ghi nhớ điều này sẽ dễ dàng hơn về mặt tâm lý nếu có một bài kiểm tra bình đẳng:

if (a == true) ...

nơi chúng tôi có thể được nhắc kiểm tra null. Vì vậy, hình thức rút gọn chỉ an toàn khi alà một nguyên thủy.

Đối với bản thân tôi bây giờ có các khuyến nghị:

  • Không bao giờ sử dụng null cho logic 3 giá trị. Chỉ sử dụng đúng và sai.
  • KHÔNG BAO GIỜ trở lại Booleantừ một phương thức như nó có thể null. Chỉ trở về boolean.
  • Chỉ sử dụng Booleanđể gói các phần tử trong các thùng chứa hoặc đối số cho các phương thức yêu cầu các đối tượng

5
Đừng sử dụng "Boolean mới (bất cứ điều gì)". Điều đó sẽ khởi tạo một Boolean mới trên heap. Nhưng Boolean là bất biến. Sử dụng "Boolean.valueOf (bất cứ điều gì)" sẽ tạo ra một tham chiếu trỏ đến Boolean.TRUE hoặc Boolean.False tùy thuộc vào bất cứ điều gì.
simbo1905

1
Một trong nhiều vấn đề với Java (IMHO sau 12 năm) là sự không nhất quán trong cách tiếp cận các giá trị null mà các ngôn ngữ cũ cũng có. Nhìn vào Scala, nó có khái niệm về một Tùy chọn được gõ có thể là null hoặc có thể có một giá trị (các lớp con Không hoặc Một số). Sau đó, bạn có thể gọi myOption.getOrElse (defaultValue). Xem scala-lang.org/api/civerse/scala/Option.html không có gì phức tạp về tính năng này. Tuy nhiên, vì nó được tích hợp vào ngôn ngữ JVM mới, nhiều thư viện sử dụng nó. Điều đó làm cho quy mô "sửa chữa" một số vấn đề "thế kỷ trước" của Java nhưng nó vẫn biên dịch thành các tệp lớp chạy trên JRE.
simbo1905

10

Các lớp Wrapper cho nguyên thủy có thể được sử dụng khi các đối tượng được yêu cầu, các bộ sưu tập là một mẫu tốt.

Hãy tưởng tượng bạn cần một lý do nào đó lưu trữ một chuỗi booleantrong một ArrayList, điều này có thể được thực hiện bằng quyền anh booleantrongBoolean .

Có một vài từ về điều này ở đây

Từ tài liệu:

Như bất kỳ lập trình viên Java nào cũng biết, bạn không thể đặt một int (hoặc giá trị nguyên thủy khác) vào một bộ sưu tập. Các bộ sưu tập chỉ có thể chứa các tham chiếu đối tượng, vì vậy bạn phải đóng các giá trị nguyên thủy vào lớp trình bao bọc thích hợp (là Integer trong trường hợp int). Khi bạn lấy đối tượng ra khỏi bộ sưu tập, bạn sẽ nhận được Số nguyên mà bạn đặt vào; nếu bạn cần một int, bạn phải hủy hộp Integer bằng phương thức intValue. Tất cả các quyền anh và unboxing này là một nỗi đau, và làm lộn xộn mã của bạn. Tính năng autoboxing và unboxing tự động hóa quá trình, loại bỏ sự đau đớn và lộn xộn.

http://docs.oracle.com/javase/1.5.0/docs/guide/lingu/autoboxing.html


3

Booleantrình bao bọc hữu ích khi bạn muốn xem giá trị được gán hay không ngoài truefalse . Nó có ba trạng thái sau:

  • Thật
  • Sai
  • Không xác định đó là null

Trong khi đó booleanchỉ có hai trạng thái:

  • Thật
  • Sai

Sự khác biệt trên sẽ làm cho nó hữu ích trong Danh sách các Booleangiá trị, trong đó có thể có True, Falsehoặc Null.


Không, nó không có trạng thái null, đó là tài liệu tham khảo.
Matsemann

Ý tôi là Bolean có thể được sử dụng để xác định Đúng / Sai và Không xác định.
Ramesh PVK

3

Tôi cho rằng trong một số trường hợp, bạn nên có một cơ chế để phân biệt trường Boolean đã đặt giá trị hay chưa.


1

Mục đích chính của Boolean là giá trị null. Giá trị Null cho biết, thuộc tính đó không được xác định , ví dụ: lấy cột nullable cơ sở dữ liệu.

Nếu bạn thực sự cần chuyển đổi mọi thứ từ boolean nguyên thủy sang Boolean, thì bạn có thể sử dụng cách sau để hỗ trợ mã cũ:

Boolean set = Boolean.FALSE; //set to default value primitive value (false)
...
if (set) ...

6
"Mục đích chính là giá trị null". Không, mục đích chính của Boolean là truyền tham chiếu đến boolean dưới dạng đối tượng.
dùng606723

@ user606723 đồng ý, tôi đã đề cập đến trường hợp cơ sở dữ liệu trong tâm trí của tôi khi tôi đang viết.
JMelnik

1

Có nhiều cách sử dụng cho giá trị ** null ** trong trình bao bọc Boolean! :)

Ví dụ: bạn có thể có trong một trường có tên là "bản tin" cho biết người dùng muốn hay không muốn nhận bản tin từ trang web của bạn. Nếu người dùng không chọn một giá trị trong trường này, bạn có thể muốn thực hiện một hành vi mặc định cho tình huống đó (gửi? Không gửi?, Câu hỏi lại?, V.v.). Rõ ràng, không được đặt (hoặc không được chọn hoặc ** null **), không giống với đúng hoặc sai.

Nhưng, nếu "không được đặt" không áp dụng cho mô hình của bạn, đừng thay đổi nguyên hàm boolean;)


1

Trong một định nghĩa chặt chẽ của một phần tử boolean, chỉ có hai giá trị. Trong một thế giới hoàn hảo, điều đó sẽ là sự thật. Trong thế giới thực, yếu tố có thể bị thiếu hoặc chưa biết. Thông thường, điều này liên quan đến đầu vào của người dùng. Trong một hệ thống dựa trên màn hình, nó có thể bị buộc phải chỉnh sửa. Trong một thế giới hàng loạt sử dụng cơ sở dữ liệu hoặc đầu vào XML, phần tử có thể dễ dàng bị thiếu.

Vì vậy, trong thế giới không hoàn hảo mà chúng ta đang sống, đối tượng Boolean tuyệt vời ở chỗ nó có thể đại diện cho trạng thái bị thiếu hoặc chưa biết là null. Rốt cuộc, máy tính chỉ mô hình hóa thế giới thực nên tính đến tất cả các trạng thái có thể và xử lý chúng bằng cách ném ngoại lệ (chủ yếu là vì có những trường hợp sử dụng trong đó ném ngoại lệ sẽ là phản ứng chính xác).

Trong trường hợp của tôi, đối tượng Boolean là câu trả lời hoàn hảo vì đôi khi XML đầu vào bị thiếu phần tử và tôi vẫn có thể nhận được một giá trị, gán nó cho Boolean và sau đó kiểm tra null trước khi thử sử dụng thử nghiệm đúng hay sai với nó .

Chỉ cần 2 xu của tôi.


1

Đối với tất cả các câu trả lời hay ở trên, tôi sẽ chỉ đưa ra một ví dụ cụ thể trong Java servlet HttpSession lớp . Hy vọng ví dụ này giúp làm rõ một số câu hỏi mà bạn vẫn có thể có.

Nếu bạn cần lưu trữ và truy xuất các giá trị cho một phiên, bạn sử dụng phương thức setAttribute(Chuỗi, Đối tượng) và getAttribute(Chuỗi, Đối tượng). Vì vậy, đối với giá trị boolean, bạn buộc phải sử dụng lớp Boolean nếu bạn muốn lưu trữ nó trong một phiên http.

HttpSession sess = request.getSession(false);
Boolean isAdmin = (Boolean) sess.getAttribute("admin");
if (! isAdmin) ...

Dòng cuối cùng sẽ gây ra NullPointerExceptionnếu giá trị thuộc tính không được đặt. (đó là lý do dẫn tôi đến bài viết này). Vì vậy, trạng thái 3 logic là ở đây, cho dù bạn có muốn sử dụng nó hay không.


0

Cách tốt nhất là tránh hoàn toàn booleans, vì mọi boolean đều ngụ ý rằng bạn có một câu lệnh có điều kiện ở bất kỳ nơi nào khác trong mã của bạn (xem http://www.antiifcampaign.com/ và câu hỏi này: Bạn có thể viết bất kỳ thuật toán nào mà không có câu lệnh if ? ).

Tuy nhiên, thực tế bạn thỉnh thoảng phải sử dụng booleans, nhưng, như bạn đã tự mình phát hiện ra, việc xử lý Booleans dễ bị lỗi hơn và cồng kềnh hơn. Vì vậy, tôi sẽ đề nghị sử dụng booleans bất cứ nơi nào có thể. Các ngoại lệ từ đây có thể là một cơ sở dữ liệu kế thừa với các cột boolean nullable, mặc dù tôi cũng sẽ cố gắng che giấu điều đó trong ánh xạ của mình.


Đối phó với Booleans dễ bị lỗi như giao dịch với bất kỳ Đối tượng nào khác. BTW, liên kết chống lại sự phổ biến của IFs để kiểm tra loại, không sử dụng chung. Và đến lượt nó, điều đó "nguy hiểm" vì nó làm cho việc sửa đổi trở nên khó khăn hơn. Vì vậy, không có gì sai với IFs mỗi se.
Smith

Không phải là một câu trả lời cho câu hỏi.
Matsemann

@MisterSmith Imho một cờ boolean thường bị sử dụng sai làm biến kiểm tra kiểu, vì vậy liên kết cũng có thể áp dụng ở đây. Nó chỉ nên là một gợi ý mà người ta nên suy nghĩ về việc liệu boolean có phải là công cụ phù hợp trong một tình huống nhất định hay không. Câu nói "tránh booleans hoàn toàn" tất nhiên là rất triệt để và thực tế là không thể, đó là lý do tại sao tôi thêm đoạn thứ hai. Tôi cũng đã thêm một "dễ bị lỗi hơn và cồng kềnh hơn" để làm rõ mọi thứ.
Roland Schneider

0

Boolean có thể rất hữu ích khi bạn cần ba trạng thái. Giống như trong kiểm thử phần mềm nếu Kiểm tra được thông qua gửi đúng, nếu thất bại gửi sai và nếu trường hợp kiểm tra bị gián đoạn gửi null sẽ biểu thị trường hợp kiểm tra không được thực thi.


2
Sẽ không enums là tốt nhất cho điều này? Trái ngược với khả năng mang lại NullPulumExceptions bất ngờ cho khách hàng, enums sẽ xác định rõ ràng "trạng thái"
Kartik Chugh

Luôn luôn thích enum thay vì booleans trong máy trạng thái. Bạn không bao giờ biết khi nào một nhà nước thứ tư mới đến trong yêu cầu kinh doanh.
AnupamChugh
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.