ผลของตัวดำเนินการ Bitwise บนบูลีนใน Java


118

ตัวดำเนินการระดับบิตควรจะเดินทางตัวแปรและดำเนินการทีละนิด ในกรณีของจำนวนเต็ม longs ตัวอักษรนี้เหมาะสม ตัวแปรเหล่านี้สามารถมีค่าเต็มช่วงบังคับตามขนาด

อย่างไรก็ตามในกรณีของบูลีนบูลีนสามารถมีได้เพียงสองค่าเท่านั้น 1 = จริงหรือ 0 = เท็จ แต่ไม่ได้กำหนดขนาดของบูลีน อาจมีขนาดใหญ่เท่าไบต์หรือเล็กหน่อยก็ได้

แล้วผลของการใช้ตัวดำเนินการแบบบิตต่อบูลีนคืออะไร? JVM แปลเป็นตัวดำเนินการตรรกะปกติและดำเนินการต่อไปหรือไม่? มันถือว่าบูลีนเป็นเอนทิตีบิตเดียวสำหรับวัตถุประสงค์ของการดำเนินการหรือไม่? หรือผลลัพธ์ไม่ได้กำหนดพร้อมกับขนาดของบูลีน?


1
ฉันคิดว่าคุณไม่สามารถใช้ตัวดำเนินการแบบบิตในบูลีนได้ เฉพาะตัวเลข ฉันแน่ใจว่า ~ จะไม่ทำงานฉันไม่รู้ว่าโอเปอเรเตอร์รายอื่นเป็นอย่างไร
Martijn Courteaux

4
คุณสามารถใช้บางส่วนเราเพิ่งค้นพบ | ใช้ในรหัสเดิมของเรา เรากำลังลบออก แต่รหัสนี้รวบรวมและใช้งานได้
Daniel Bingham

9
เนื่องจากตัวหนึ่งลัดวงจรและอีกอันไม่ได้ (ดูคำตอบของ mobrule) ก่อนที่คุณจะเปลี่ยน | ถึง || คุณอาจต้องการตรวจสอบให้แน่ใจว่านิพจน์บูลีนที่ตามมาไม่มีผลข้างเคียงใด ๆ ที่โปรแกรมเมอร์ดั้งเดิมตั้งใจจะดำเนินการเสมอไป
John M Gant

คำตอบ:


122

ผู้ประกอบการ&, ^และ|ผู้ประกอบการระดับบิตเมื่อถูกดำเนินการเป็นชนิดหนึ่งดั้งเดิม เป็นตัวดำเนินการทางตรรกะเมื่อตัวถูกดำเนินการเป็นบูลีนและมีการระบุพฤติกรรมของพวกเขาในกรณีหลัง ดูส่วน 15.22.2 ของข้อมูลจำเพาะ Java Languageสำหรับรายละเอียด


57
โดยเฉพาะ & และ ^ และ | เป็นตัวดำเนินการบูลีนเชิงตรรกะที่ไม่ลัดวงจร
Ken

14
นี่คือลิงค์โดยตรงไปยังส่วนที่กล่าวถึงข้างต้น: docs.oracle.com/javase/specs/jls/se7/html/…
Andy Thomas

หากข้างต้นเป็นจริงเหตุใดideone.com/oGSF7c จึงโยนข้อยกเว้นตัวชี้ว่าง หากตัว|=ดำเนินการเป็นตรรกะโปรแกรมไม่ควรเรียกใช้x.getValue()คำสั่ง
ikromm

1
@JohnKrommidas x ของคุณเป็นโมฆะซึ่งเป็นสาเหตุที่คุณได้รับ NullPointerException คุณต้องสร้างอินสแตนซ์
เบ็น

4
@ เบ็นอย่างที่ @ เคนกล่าวว่าตรรกะไม่ลัดวงจรดังนั้นส่วนที่สองจึงได้รับการประเมิน จึงa || x.foo()ปลอดภัยถ้า x เป็นโมฆะ แต่a | x.foo()ไม่ใช่ ตามกฎเช่นเดียวกับ|= |
Michael Smith

86

การใช้ตัวดำเนินการระดับบิตสามารถหลีกเลี่ยงพฤติกรรมการลัดวงจรได้:

boolean b = booleanExpression1() && booleanExpression2();
boolean b = booleanExpression1() & booleanExpression2();

หากbooleanExpression1()ประเมินเป็นfalseแล้ว
booleanExpression2()จะไม่ได้รับการประเมินในกรณีแรกและ
booleanExpression2()(และผลข้างเคียงใด ๆ ที่อาจมี) จะถูกประเมินในกรณีที่สอง


2
และการทำงานในระดับบิตมักจะทำงานเร็วกว่าการลัดวงจร (หากการประเมินนั้นง่าย)
rds

1
บิต&จะเร็วขึ้น แต่การเรียกไปยังฟังก์ชันที่สองอาจถูกละเว้นเมื่อใช้&&
NatNgs

20

นอกเหนือจากสิ่งที่กล่าวถึงในคำตอบอื่น ๆ ก็เป็นที่น่าสังเกตว่า&&และ||มีความสำคัญที่แตกต่างจากและ&|

แยกจากตารางลำดับความสำคัญ (โดยมีลำดับความสำคัญสูงสุดอยู่ด้านบนสุด)

bitwise AND                 &
bitwise exclusive OR        ^
bitwise inclusive OR        |
logical AND                 &&
logical OR                  ||

สิ่งนี้มีความหมายกับคุณอย่างไร?

ไม่มีอะไรแน่นอนตราบใดที่คุณติดกับอย่างใดอย่างหนึ่งเท่านั้น&และ|หรือเฉพาะและ&&||

แต่เนื่องจาก|มีลำดับความสำคัญสูงกว่า&&(เมื่อเทียบกับ||ซึ่งมีลำดับความสำคัญต่ำกว่า) การผสมอย่างอิสระอาจนำไปสู่พฤติกรรมที่ไม่คาดคิด

ดังนั้นa && b | c && dเป็นเช่นเดียวกับa && (b | c) && d,
ตรงข้ามกับการซึ่งจะเป็นa && b || c && d(a && b) || (c && d)

เพื่อพิสูจน์ว่ามันไม่เหมือนกันให้พิจารณาสารสกัดจากตารางความจริง:

a | b | c | d | (b|c) | (a&&b) | (c&&d) | a && (b|c) && d | (a&&b) || (c&&d)
F | T | T | T |   T   |   F    |    T   |         F       |        T
                                                  ^                ^
                                                  |- not the same -|

หากคุณต้องการให้หรือมีลำดับความสำคัญสูงกว่า AND คุณสามารถใช้|และ&&ร่วมกันได้ แต่ไม่แนะนำให้ใช้

แต่คุณควรใส่ไว้ในวงเล็บเพื่อชี้แจงลำดับความสำคัญเมื่อใดก็ตามที่ใช้สัญลักษณ์ต่างกันเช่น(a && b) || c(วงเล็บเพื่อชี้แจงลำดับความสำคัญ) a && b && c(ไม่ต้องใช้วงเล็บ)


3

แม้ว่ามันจะได้ผลคุณก็ไม่ควรทำ ข้อกำหนดภาษากำหนดตัวดำเนินการแบบบิตต่อเมื่อตัวถูกดำเนินการทั้งสองเป็นประเภทจำนวนเต็มดั้งเดิมหรือทั้งสองเป็นประเภทบูลีน ฉันจะบอกว่าสำหรับกรณีอื่น ๆ ผลลัพธ์ไม่ได้กำหนดไว้:

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5228


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