ตรวจสอบว่า null บูลีนเป็นผลลัพธ์ที่แท้จริงยกเว้น


169

ฉันมีรหัสต่อไปนี้:

Boolean bool = null;

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

ทำไมการตรวจของฉันถึงตัวแปรบูลีน "บูล" จึงทำให้เกิดข้อยกเว้น? มันควรจะกระโดดข้ามคำสั่ง if ทันทีหรือไม่เมื่อเห็น "เห็นว่ามันไม่จริงเหรอ? เมื่อฉันลบคำสั่ง if หรือตรวจสอบหากไม่เป็นโมฆะข้อยกเว้นจะหายไป


3
คำตอบข้างต้นเกี่ยวกับการแกะกล่องวัตถุนั้นถูกต้องทั้งหมด อย่างไรก็ตามเพื่อความสมบูรณ์อย่างไรก็ตามคุณสามารถเปลี่ยนรหัสของคุณเพื่อใช้ "บูลีน" แบบดั้งเดิมแทนการใช้ออบเจกต์ "Boolean" คุณควรรีเฟรชตัวเองเกี่ยวกับความแตกต่างระหว่างดั้งเดิมและวัตถุ
Marvo

ในขณะเดียวกัน ... if (bool == Boolean.TRUE)ประเมินเท็จโดยไม่สร้างข้อยกเว้น ไม่แน่ใจว่านี่เป็นเจตนาในกรณีที่ฉันเพิ่งพบ
simon.watts

2
@ simon.watts ที่จะเป็นเท็จสำหรับboolการเป็นnullหรือถ้าBooleanถูกสร้างขึ้นอย่างชัดเจน (และไม่อ้างอิงถึงBoolean.TRUE) ดังนั้นไม่แนะนำ เมื่อเทียบกับการif (Boolean.TRUE.equals(bool))ที่จะทำงานตามที่คาดไว้รวมถึงได้อย่างปลอดภัยการจัดการnullค่า
StaxMan

คำตอบ:


171

เมื่อคุณมีbooleanมันสามารถเป็นได้ทั้งหรือtrue falseแต่เมื่อคุณมีBooleanมันสามารถเป็นได้ทั้งBoolean.TRUE, Boolean.FALSEหรือnullเป็นวัตถุอื่น ๆ

ในกรณีเฉพาะของคุณข้อความของคุณBooleanคือnullและifคำสั่งจะทำให้เกิดการแปลงโดยปริยายbooleanNullPointerExceptionที่ก่อให้เกิด คุณอาจต้องการแทน:

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

23
ในทางเทคนิค a Booleanสามารถเป็นอินสแตนซ์ที่แท้จริงได้ไม่Boolean.TRUEจำกัด จำนวน new Boolean(true)เช่น
Steve Kuo

1
ผมต่อสู้เพื่อให้เข้าใจว่าทำไมif (myBoolean)(ที่myBooleanเป็นBoolean) ไม่ยกรวบรวมข้อผิดพลาดหรืออย่างน้อยเตือน นี่คือ gotcha แน่นอน
Josh M.

1
@JoshM นี่เป็นเพราะ Java ทำการชกมวยและการแกะกล่องปิด : docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius

3
@Vinicius แน่นอน แต่คอมไพเลอร์ควรทำ null สำหรับเราในกรณีนี้โดยใช้คำเตือนของคอมไพเลอร์อย่างน้อย
Josh M.

2
@JoshM ไม่สามารถเห็นด้วยเพิ่มเติม :)
Vinicius

402

หากคุณไม่ชอบการตรวจสอบโมฆะพิเศษ:

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

1
@AvrDragon: จำเป็นต้องเท่ากับหรือไม่ ผู้ประกอบการ == ทำงานที่นี่เนื่องจากบูลีนมีเพียงสองค่า
Atul

7
@Atul ใช่ต้องเท่ากับที่นี่ เพราะ (บูลีนใหม่ (จริง) == บูลีนใหม่ (จริง)) เป็น .... เท็จ เหตุผล: บูลีนเป็นเพียงคลาสและสามารถมีได้หลายอินสแตนซ์เหมือนกับคลาสอื่นใน java
AvrDragon

35
ใช่มันเป็นความอัปยศผู้สร้างควรเป็นแบบส่วนตัวดังนั้นจึงมั่นใจได้ว่าเป็น twingleton ...
fortran

15
@fortran +1 สำหรับ "twingleton"
Bennett McElwee

1
ไม่มีจุดใดที่ใช้ Apache BooleanUtils เหนือสำนวนนี้
StaxMan

82

ใช้ BooleanUtils อาปาเช่

(หากประสิทธิภาพสูงสุดเป็นสิ่งสำคัญที่สุดในโครงการของคุณให้ดูคำตอบอื่นสำหรับโซลูชันดั้งเดิมที่ไม่ต้องการรวมถึงไลบรารีภายนอก)

อย่าประดิษฐ์ล้อใหม่ ใช้ประโยชน์จากสิ่งที่สร้างและใช้งานแล้วisTrue():

BooleanUtils.isTrue( bool );

ตรวจสอบว่าBooleanค่าเป็นจริงการจัดการnullโดยกลับมาfalseโดยกลับ

หากคุณไม่ได้ จำกัด อยู่ที่ห้องสมุดที่คุณกำลัง "อนุญาต" ที่จะรวมถึงมีพวงของฟังก์ชั่นช่วยที่ดีสำหรับทุกประเภทของกรณีการใช้งานรวมถึงและBooleans Stringsฉันขอแนะนำให้คุณอ่านไลบรารี Apache ต่างๆและดูว่ามีอะไรบ้าง


59
การปรับมุมล้อใหม่ไม่ได้เลวร้ายนักเมื่อทางเลือกอื่นกำลังใช้ไลบรารี่ภายนอกสำหรับบางสิ่งพื้นฐานเช่นนี้
พอล Manta

3
@PaulManta ฉันยอมรับว่านี่เป็นสิ่งเดียวที่คุณเคยใช้ในห้องสมุด Apache Utils แต่ความคิดที่แนะนำคือการ "อ่าน" ห้องสมุดเพื่อแสดงให้คุณเห็นถึงฟังก์ชั่นที่เป็นประโยชน์อื่น ๆ
Joshua Pinter

1
มีโทษประสิทธิภาพสำหรับการใช้ไลบรารีเหล่านี้ ดังนั้นสำหรับสิ่งพื้นฐานดังกล่าวซึ่งเป็นส่วนหนึ่งของภาษาคุณไม่ควรใช้ห้องสมุด
ACV

6
ห้องสมุดนั่นคือการพลิกโฉมวงล้อ ฉันพยายามหลีกเลี่ยงไลบรารีดังกล่าวมากที่สุด
mschonaker

3
@mschonaker หาก Apache BooleanUtils กำลังสร้างล้อใหม่ล้อเดิมคืออะไร แนวคิดคือการหลีกเลี่ยงการสร้างฟังก์ชันตัวช่วยมากมายที่เลียนแบบสิ่งที่ได้ทำไปแล้วในห้องสมุดเช่นนี้ ฉันยังใช้toStringYesNoจากห้องสมุดนี้ในแอปพลิเคชันทั้งหมดของฉัน
Joshua Pinter

13

Booleannullประเภทสามารถ คุณจำเป็นต้องทำเช็คที่คุณได้ตั้งค่าให้nullnull

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

3
เกิดอะไรขึ้นกับคำตอบนี้? ไม่ใช่การตรวจสอบบูลที่จะทำให้เกิดข้อยกเว้น downvotes ที่ไม่จำเป็น
dodexahedron

2
ฉันเห็นด้วยว่ามันเป็นคำตอบที่สมเหตุสมผลอย่างสมบูรณ์แบบ คุณสามารถกำจัดข้อยกเว้นได้
Marvo

14
การแจกแจงข้อยกเว้นนั้นไม่จำเป็นและนอกจากนั้นมันกำลังทำในลักษณะที่เป็นตัวอย่างที่ไม่ดีสำหรับผู้เริ่มต้น สิ่งนี้สมควรได้รับ downvote, IMO (ใช่ ... ฉันรู้ว่ามันมาจากรหัสตัวอย่าง แต่การทำซ้ำในคำตอบดูเหมือนจะรับรอง)
สตีเฟ่นซี

1
แล้วหนทางที่ถูกต้องคืออะไร? ฉันไม่เห็นคำตอบของคุณที่นี่
Marvo

5
วิธีที่ถูกต้องคือสิ่งที่กล่าวมาข้างต้น .. นอกจากนี้การจัดการข้อยกเว้นนั้นกว้างเกินไปและไม่สนับสนุน
vellvisher

8

หรือด้วยพลังของ Java 8 ซึ่งเป็นทางเลือกคุณสามารถทำเคล็ดลับดังกล่าวได้:

Optional.ofNullable(boolValue).orElse(false)

:)


5

บูลีนเป็นคลาส wrapper วัตถุสำหรับบูลีนดั้งเดิม คลาสนี้ในฐานะคลาสใด ๆ สามารถเป็นโมฆะได้ สำหรับเหตุผลด้านประสิทธิภาพและความจำการใช้แบบดั้งเดิมนั้นดีที่สุดเสมอ

คลาส wrapper ใน Java API ทำหน้าที่สองวัตถุประสงค์หลัก:

  1. เพื่อให้กลไกในการ "ห่อ" ค่าดั้งเดิมในวัตถุเพื่อให้สามารถรวมเข้ากับกิจกรรมที่สงวนไว้สำหรับวัตถุเช่นเพิ่มเข้าไปในคอลเล็กชันหรือส่งคืนจากวิธีที่มีค่าส่งคืนวัตถุ
  2. เพื่อจัดประเภทของฟังก์ชั่นยูทิลิตี้สำหรับดั้งเดิม ฟังก์ชันเหล่านี้ส่วนใหญ่เกี่ยวข้องกับการแปลงต่าง ๆ : การแปลงแบบดั้งเดิมไปยังและจากวัตถุสตริงและการแปลงแบบดั้งเดิมและวัตถุสตริงไปยังและจากฐานที่แตกต่างกัน (หรือฐาน) เช่นไบนารีฐานแปดและเลขฐานสิบหก

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


0

ในขณะที่ตัวแปรบูลของคุณชี้เป็นโมฆะคุณจะได้รับ NullPointerException เสมอคุณต้องเริ่มต้นตัวแปรก่อนที่ไหนสักแห่งที่มีค่าไม่เป็นโมฆะและแก้ไขค่านั้น


1
ถ้าเป็นเช่นนั้นcatchบล็อกจะจัดการกับ NullPointerException ปัญหาที่นี่คือว่า OP พยายามที่จะยกเลิกการอ้างอิงเป็นโมฆะในกล่องดั้งเดิม
Mike Adler

"you always" - ไม่เสมอไปยกเว้นโค้ดตัวอย่างแบบง่ายที่ไม่ได้ทำอะไรเลยระหว่างการเริ่มต้นตัวแปรถึงnullแล้วทดสอบ รหัสจริงน่าจะไม่ใช่ว่าง่ายหรือการifทดสอบทั้งหมดจะถูกลบออก
nnnnnn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.