Kiểm tra xem null Boolean có phải là kết quả đúng không


169

Tôi có đoạn mã sau:

Boolean bool = null;

try 
{
    if (bool)
    {
        //DoSomething
    }                   
} 
catch (Exception e) 
{
    System.out.println(e.getMessage());             
}

Tại sao việc kiểm tra biến "Bool" của Boolean lại dẫn đến một ngoại lệ? Không phải nó nên nhảy ngay qua câu lệnh if khi nó "thấy" rằng nó không đúng? Khi tôi xóa câu lệnh if hoặc kiểm tra nếu nó KHÔNG null, ngoại lệ sẽ biến mất.


3
Các câu trả lời ở trên về unboxing đối tượng đều đúng. Tuy nhiên, để hoàn thiện hơn, bạn cũng có thể thay đổi mã của mình để sử dụng "boolean" nguyên thủy thay vì trình bao bọc đối tượng "Boolean". Bạn cũng nên làm mới bản thân về sự khác biệt giữa nguyên thủy và Vật thể.
Marvo

Trong khi đó ... if (bool == Boolean.TRUE)đánh giá sai mà không tạo ra ngoại lệ. Không chắc chắn nếu điều này là cố ý trong trường hợp tôi vừa tìm thấy.
simon.watts

2
@ simon.watts sẽ sai boolkhi là nullOR nếu Booleanđược xây dựng rõ ràng (và không phải là tham chiếu đến Boolean.TRUE). Vì vậy, không khuyến khích; trái ngược với if (Boolean.TRUE.equals(bool))đó sẽ làm việc như mong đợi, bao gồm nullgiá trị xử lý an toàn .
StaxMan

Câu trả lời:


170

Khi bạn có booleannó có thể là truehoặc false. Tuy nhiên, khi bạn có một Booleannó có thể là một trong hai Boolean.TRUE, Boolean.FALSEhoặc nullnhư bất kỳ đối tượng khác.

Trong trường hợp cụ thể của bạn, bạn Booleannullvà các iftuyên bố gây nên một chuyển đổi ngầm để booleansản sinh ra NullPointerException. Bạn có thể cần thay thế:

if(bool != null && bool) { ... }

23
Về mặt kỹ thuật Booleancó thể là bất kỳ số lượng các trường hợp thực sự, không chỉ Boolean.TRUE. Ví dụ new Boolean(true).
Steve Kuo

1
Tôi đấu tranh để hiểu tại sao if (myBoolean)(nơi myBooleanBoolean) không nâng cao một lỗi biên dịch hoặc ít nhất là một cảnh báo. Đây là một gotcha chắc chắn.
Josh M.

1
@JoshM. Điều này là do Java không BoxingUnboxing của wrappers: docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius

3
@Vinicius chắc chắn, nhưng trình biên dịch nên thực hiện null cho chúng tôi trong trường hợp này, thông qua một cảnh báo trình biên dịch ít nhất.
Josh M.

2
@JoshM. Không thể đồng ý nhiều hơn :)
Vinicius

402

Nếu bạn không thích kiểm tra null thêm:

if (Boolean.TRUE.equals(value)) {...}

1
@AvrDragon: có bằng không? Toán tử == hoạt động ở đây vì Boolean chỉ có hai giá trị
Atul

7
@Atul Có, bằng được yêu cầu ở đây. Bởi vì (Boolean mới (true) == Boolean mới (true)) là .... false. Lý do: Boolean chỉ là một lớp và có thể có nhiều phiên bản như bất kỳ lớp nào khác trong java.
AvrDragon

35
vâng, đó là một sự xấu hổ, nhà xây dựng nên riêng tư để đảm bảo rằng đó là một twingleton ...
fortran

15
@fortran +1 cho "twingleton".
Bennett McElwee

1
Hoàn toàn không có điểm nào trong việc sử dụng BooleanUtils của Apache đối với thành ngữ này.
StaxMan

82

Sử dụng BooleanUtils Apache .

(Nếu hiệu suất cao nhất là ưu tiên quan trọng nhất trong dự án của bạn thì hãy xem một trong những câu trả lời khác cho giải pháp gốc không yêu cầu bao gồm thư viện bên ngoài.)

Đừng phát minh lại bánh xe. Tận dụng những gì đã được xây dựng và sử dụng isTrue():

BooleanUtils.isTrue( bool );

Kiểm tra nếu một Booleangiá trị là đúng, xử lý nullbằng cách trả lại false.

Nếu bạn không giới hạn trong các thư viện mà bạn "được phép" đưa vào, có một loạt các chức năng trợ giúp tuyệt vời cho tất cả các loại trường hợp sử dụng, bao gồm BooleansStrings. Tôi đề nghị bạn nên kiểm tra các thư viện Apache khác nhau và xem những gì họ đã cung cấp.


59
Phát minh lại bánh xe dường như không tệ lắm khi người thay thế đang sử dụng một thư viện bên ngoài cho một cái gì đó cơ bản như thế này.
Paul Manta

3
@PaulManta Tôi đồng ý nếu đây là điều duy nhất bạn từng sử dụng trong các thư viện Apache Utils, nhưng ý tưởng được đề xuất là "kiểm tra" các thư viện để thể hiện bản thân với các chức năng hữu ích khác.
Joshua Pinter

1
Có một hình phạt hiệu suất cho việc sử dụng các thư viện. Vì vậy, đối với những thứ cơ bản như vậy là một phần của ngôn ngữ, bạn không nên sử dụng các thư viện.
ACV

6
Thư viện đó đang phát minh lại bánh xe. Tôi cố gắng tránh các thư viện như vậy càng nhiều càng tốt.
mschonaker 24/07/2015

3
@mschonaker Nếu Apache BooleanUtils đang phát minh lại bánh xe, thì bánh xe ban đầu là gì? Ý tưởng là để tránh tạo ra một loạt các hàm trợ giúp bắt chước những gì đã được thực hiện trong các thư viện như thế này. Tôi cũng sử dụng toStringYesNotừ thư viện này trong tất cả các ứng dụng của mình.
Joshua Pinter

13

Booleancác loại có thể được null. Bạn cần phải nullkiểm tra như bạn đã đặt null.

if (bool != null && bool)
{
  //DoSomething
}                   

3
Có gì sai với câu trả lời này? Đó không phải là việc kiểm tra bool sẽ ném ngoại lệ. Downvote không cần thiết.
dodexahedron

2
Tôi đồng ý đó là một câu trả lời hoàn toàn hợp lý. Bạn có thể thoát khỏi việc xử lý ngoại lệ mặc dù.
Marvo

14
Việc xử lý ngoại lệ là không cần thiết, và bên cạnh nó đang được thực hiện theo cách là một ví dụ tồi tệ cho người mới bắt đầu. Điều này xứng đáng với một downvote, IMO. (Yea ... Tôi biết nó xuất phát từ mã ví dụ, nhưng lặp lại nó trong Câu trả lời dường như để chứng thực nó.)
Stephen C

1
Cách nào là QUYỀN? Tôi không thấy câu trả lời của bạn ở đây.
Marvo

5
Cách đúng là cách trên..không xử lý ngoại lệ. Ngoài ra, việc xử lý Ngoại lệ quá chung chung và không được khuyến khích.
vellvisher

8

Hoặc với sức mạnh của Java 8 Tùy chọn, bạn cũng có thể thực hiện thủ thuật đó:

Optional.ofNullable(boolValue).orElse(false)

:)


5

Boolean là lớp bao bọc đối tượng cho boolean nguyên thủy. Lớp này, như bất kỳ lớp nào, thực sự có thể là null. Đối với lý do hiệu suất và bộ nhớ, tốt nhất là luôn sử dụng nguyên thủy.

Các lớp trình bao bọc trong API Java phục vụ hai mục đích chính:

  1. Để cung cấp một cơ chế cho gói quấn các giá trị nguyên thủy của Edward trong một đối tượng để có thể đưa các nguyên thủy vào các hoạt động dành riêng cho các đối tượng, như được thêm vào Bộ sưu tập hoặc được trả về từ một phương thức có giá trị trả về đối tượng.
  2. Để cung cấp một loại chức năng tiện ích cho người nguyên thủy. Hầu hết các hàm này có liên quan đến các chuyển đổi khác nhau: chuyển đổi nguyên thủy sang và từ các đối tượng Chuỗi và chuyển đổi các đối tượng nguyên thủy và chuỗi sang và từ các cơ sở khác nhau (hoặc cơ số), chẳng hạn như nhị phân, bát phân và thập lục phân.

http://en.wikipedia.org/wiki/Primitive_wrapper_group


0

vì bool biến của bạn đang trỏ đến null, bạn sẽ luôn nhận được NullPulumException, trước tiên bạn cần khởi tạo biến ở đâu đó với giá trị không null, sau đó sửa đổi nó.


1
Nếu chỉ có vậy, catchkhối sẽ xử lý NullPulumException. Vấn đề ở đây là OP cố gắng hủy bỏ tham chiếu null thành nguyên thủy.
Mike Adler

"bạn sẽ luôn luôn" - Không phải lúc nào cũng vậy, ngoại trừ mẫu, mã đơn giản hóa không làm gì giữa việc khởi tạo biến nullvà sau đó kiểm tra nó. Có lẽ mã thực sẽ không đơn giản hoặc toàn bộ ifthử nghiệm có thể bị xóa.
nnnnnn
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.