Java & = โอเปอเรเตอร์ใช้กับ & หรือ && หรือไม่


139

ทะลึ่ง

boolean a = false;

ฉันสงสัยว่าถ้าทำ:

a &= b; 

เทียบเท่ากับ

a = a && b; //logical AND, a is false hence b is not evaluated.

หรือในทางกลับกันหมายความว่า

a = a & b; //Bitwise AND. Both a and b are evaluated.

คำตอบ:


146

จากข้อมูลจำเพาะภาษาชวา - 15.26.2 ผู้ประกอบการกำหนด

นิพจน์การมอบหมายผสมของฟอร์มE1 op= E2เทียบเท่ากับE1 = (T)((E1) op (E2))โดยที่Tเป็นประเภทE1ยกเว้นว่าE1ถูกประเมินเพียงครั้งเดียว

ดังนั้นจะเทียบเท่ากับa &= b;a = a & b;

(ในประเพณีบางอย่างการหล่อแบบนั้นสร้างความแตกต่างให้กับผลลัพธ์ แต่ในอันนี้bต้องเป็นbooleanและการหล่อแบบไม่ได้ทำอะไรเลย)

และสำหรับบันทึกa &&= b;นั้นไม่ถูกต้อง Java ไม่มี&&=ผู้ให้บริการ


ในทางปฏิบัติมีความแตกต่างความหมายเล็ก ๆ น้อย ๆ ระหว่างและa = a & b; a = a && b;(ถ้าbเป็นตัวแปรหรือค่าคงที่ผลลัพธ์จะเหมือนกันสำหรับทั้งสองรุ่นมีความแตกต่างทางความหมายเมื่อbมีนิพจน์ย่อยที่มีผลข้างเคียงเท่านั้นใน&กรณีผลข้างเคียงจะเกิดขึ้นเสมอใน&&กรณีมันเกิดขึ้นขึ้นอยู่กับมูลค่าของa.)

ในด้านประสิทธิภาพการปิดอยู่ระหว่างค่าใช้จ่ายในการประเมินbและค่าใช้จ่ายของการทดสอบและสาขาของค่าของและการประหยัดที่มีศักยภาพในการหลีกเลี่ยงงานที่ไม่จำเป็นเพื่อa aการวิเคราะห์ไม่ได้เป็นแบบตรงไปข้างหน้า แต่ถ้าค่าใช้จ่ายในการคำนวณbนั้นไม่สำคัญความแตกต่างของประสิทธิภาพระหว่างสองเวอร์ชันนั้นเล็กเกินไปที่จะพิจารณาว่าคุ้มค่า


ย่อหน้า "ในทางปฏิบัติ" ของคุณทำให้เข้าใจผิด เหตุผลเดียวที่ใช้ & มากกว่า && คือการคำนวณนิพจน์ย่อยที่ไม่สำคัญใน "b"
AlexP

ชี้แจง (อันที่จริงแล้วเรื่องไม่สำคัญไม่ได้เข้ามาจริงๆ)
สตีเฟนซี

51

ดู15.22.2 ของ JLS สำหรับตัวถูกดำเนินการบูลีนโอเป&อเรเตอร์คือบูลีนไม่ใช่ระดับบิต ความแตกต่างเพียงอย่างเดียวระหว่าง&&และ&สำหรับตัวถูกดำเนินการบูลีนก็คือว่า&&มันเป็นวงจรสั้น (หมายความว่าตัวถูกดำเนินการที่สองไม่ได้รับการประเมินถ้าตัวถูกดำเนินการครั้งแรกประเมินเป็นเท็จ)

ดังนั้นในกรณีของคุณถ้าbเป็นดั้งเดิมa = a && b, a = a & bและa &= bทุกคนทำในสิ่งเดียวกัน


2
ดังนั้น (a & = b;) จะไม่ลัดวงจรถ้า b เป็นการเรียกเมธอด? มีบางอย่างเช่นตัวดำเนินการ "&& =" หรือไม่
is7s

2
ดูเหมือนว่าสิ่งนี้จะไม่ตอบคำถาม OP ทราบแล้วเกี่ยวกับการลัดวงจร
หรือผู้ทำแผนที่


0

นี่คือวิธีทดสอบง่ายๆ:

public class OperatorTest {     
    public static void main(String[] args) {
        boolean a = false;
        a &= b();
    }

    private static boolean b() {
        System.out.println("b() was called");
        return true;
    }
}

เอาท์พุทคือb() was calledดังนั้นตัวถูกดำเนินการทางขวาจะถูกประเมิน

ดังนั้นดังกล่าวแล้วโดยคนอื่น ๆ เป็นเช่นเดียวกับa &= ba = a & b


-2

ฉันเจอสถานการณ์ที่คล้ายกันโดยใช้บูลีนซึ่งฉันต้องการหลีกเลี่ยงการโทร b () ถ้า a เป็นเท็จอยู่แล้ว

สิ่งนี้ใช้ได้กับฉัน:

a &= a && b()

25
เพื่อที่จะหลีกเลี่ยงความซ้ำซ้อน (ยังคงช่วยให้การลัดวงจร) a=a&&b()คุณก็สามารถเขียน
Unai Vivi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.