ความแตกต่างระหว่าง & และ & & ใน Java คืออะไร?


167

ฉันคิดเสมอว่า&&ตัวดำเนินการใน Java ใช้สำหรับตรวจสอบว่าตัวถูกดำเนินการบูลีนtrueหรือไม่และตัว&ดำเนินการใช้ในการดำเนินการบิตฉลาดในสองจำนวนเต็ม

เมื่อเร็ว ๆ นี้ฉันรู้ว่า&ตัวดำเนินการสามารถใช้ตรวจสอบว่าตัวถูกดำเนินการบูลีนtrueความแตกต่างเพียงอย่างเดียวที่จะตรวจสอบตัวถูกดำเนินการ RHS แม้ว่าตัวถูกดำเนินการ LHS เป็นเท็จ

ตัว&ดำเนินการใน Java โอเวอร์โหลดอยู่ภายในหรือไม่ หรือมีแนวคิดอื่น ๆ ที่อยู่เบื้องหลังเรื่องนี้?



ดำเนินการทางลัดสองครั้งหากเป็นไปได้
นิโคลัสแฮมิลตัน

คำตอบ:


278

& <- ตรวจสอบตัวถูกดำเนินการทั้งสอง
&& <- หยุดการประเมินว่าตัวถูกดำเนินการแรกประเมินว่าเป็นเท็จหรือไม่เนื่องจากผลลัพธ์จะเป็นเท็จ

(x != 0) & (1/x > 1)<- นี่หมายถึงประเมิน(x != 0)แล้วประเมิน(1/x > 1)แล้วทำเครื่องหมาย & ปัญหาคือว่าสำหรับ x = 0 นี้จะโยนข้อยกเว้น

(x != 0) && (1/x > 1)<- นี่หมายถึงประเมิน(x != 0)และเฉพาะในกรณีที่เป็นจริงแล้วประเมิน(1/x > 1)ดังนั้นหากคุณมี x = 0 นี่จะปลอดภัยอย่างสมบูรณ์และจะไม่ทิ้งข้อยกเว้นหาก (x! = 0) ประเมินว่าเป็นเท็จสิ่งทั้งหมดประเมินว่าเป็นเท็จโดยตรง (1/x > 1)โดยไม่ต้องประเมิน

แก้ไข:

exprA | exprB<- นี่หมายถึงประเมินexprAแล้วประเมินexprBจากนั้นทำ|แล้วทำ

exprA || exprB<- ที่นี้หมายถึงการประเมินexprAและมีเพียงถ้าเป็นfalseแล้วประเมินและทำexprB||


7
เหตุผลในการเขียนหนึ่ง & หรือคืออะไร ในถ้าคำสั่ง? จะไม่เร็วกว่า && และ || ทำไมเราต้องการตรวจสอบเงื่อนไขที่สองหากเรามีคำตอบอยู่แล้ว? ได้โปรดและเป็นตัวอย่างที่เป็นจริงได้ไหม
Michu93

14
@ Michu93: ตัวอย่างหนึ่งก็คือหากเงื่อนไขที่สองคือการเรียกใช้ฟังก์ชันซึ่งมีผลข้างเคียงที่คุณต้องการเสมอ เนื่องจากปกติแล้วควรหลีกเลี่ยงผลข้างเคียงจึงมีเพียงกรณีที่หายากที่คุณต้องการและฉันไม่สามารถนึกถึงตัวอย่างที่เป็นจริงได้ในขณะนี้
Heinzi

54

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

int a = 4;
int b = 7;
System.out.println(a & b); // prints 4
//meaning in an 32 bit system
// 00000000 00000000 00000000 00000100
// 00000000 00000000 00000000 00000111
// ===================================
// 00000000 00000000 00000000 00000100

2
คำถามเกี่ยวกับการดำเนินการบูลีนแบบลอจิคัลไม่ใช่การดำเนินการระดับบิต
มาร์ควิสแห่ง Lorne

21
@EJP มันช่วยให้ชาว Google ยังคงชอบฉันที่อ่านชื่อเท่านั้น
โฆษณา Infinitum

29
boolean a, b;

Operation     Meaning                       Note
---------     -------                       ----
   a && b     logical AND                    short-circuiting
   a || b     logical OR                     short-circuiting
   a &  b     boolean logical AND            not short-circuiting
   a |  b     boolean logical OR             not short-circuiting
   a ^  b     boolean logical exclusive OR
  !a          logical NOT

short-circuiting        (x != 0) && (1/x > 1)   SAFE
not short-circuiting    (x != 0) &  (1/x > 1)   NOT SAFE

ขอบคุณ Andreas สำหรับการแก้ไขบางทีคำถามอื่นอาจช่วยได้เช่น: stackoverflow.com/questions/4014535/vs-and-vs
Torres

11

ขึ้นอยู่กับประเภทของข้อโต้แย้ง ...

สำหรับอาร์กิวเมนต์จำนวนเต็มเครื่องหมายแอมเปอร์แซนด์เดียว ("&") คือตัวดำเนินการ "bit-wise AND" เครื่องหมายแอมเปอร์แซนด์สองตัว ("&&") ไม่ได้ถูกกำหนดไว้สำหรับอะไรเลยนอกจากอาร์กิวเมนต์บูลีนสองตัว

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

สำหรับประเภทอาร์กิวเมนต์และชุดค่าผสมอื่น ๆ ทั้งหมดข้อผิดพลาดในการรวบรวมควรเกิดขึ้น



7

มันเป็นไปตามที่ระบุไว้ในJLS (15.22.2) :

เมื่อทั้งสองตัวถูกดำเนินการของ &, ^ หรือ | โอเปอเรเตอร์เป็นประเภทบูลีนหรือบูลีนดังนั้นประเภทของนิพจน์โอเปอเรเตอร์แบบบิตคือบูลีน ในทุกกรณีตัวถูกดำเนินการอยู่ภายใต้การแปลง unboxing (§5.1.8) ตามความจำเป็น

สำหรับ &, ค่าผลลัพธ์เป็นจริงถ้าทั้งสองค่าตัวถูกดำเนินการเป็นจริง; มิฉะนั้นผลลัพธ์จะเป็นเท็จ

สำหรับ ^ ค่าผลลัพธ์เป็นจริงถ้าค่าตัวถูกดำเนินการแตกต่างกัน มิฉะนั้นผลลัพธ์จะเป็นเท็จ

สำหรับ | ค่าผลลัพธ์เป็นเท็จถ้าทั้งสองค่าตัวถูกดำเนินการเป็นเท็จ มิฉะนั้นผลลัพธ์จะเป็นจริง

ว่า "เคล็ดลับ" คือว่า&เป็นจำนวนเต็ม Bitwise ผู้ประกอบการเช่นเดียวกับผู้ประกอบการตรรกะบูลีน ดังนั้นทำไมไม่เห็นว่านี่เป็นตัวอย่างสำหรับการใช้งานมากเกินไปมีเหตุผล


7

ฉันคิดว่าคำตอบของฉันสามารถเข้าใจได้มากขึ้น:

มีสองความแตกต่างระหว่างมี และ&&&

หากพวกเขาใช้เป็นตรรกะและ

&และ&&อาจเป็นตรรกะANDเมื่อผลลัพธ์การแสดงออกทางซ้าย&หรือ&&ขวาทั้งหมดเป็นจริงผลการดำเนินงานทั้งหมดอาจเป็นจริง

เมื่อใด&และ&&ตามเหตุผลANDจะมีความแตกต่าง:

เมื่อใช้&&เป็นตรรกะANDหากผลลัพธ์การแสดงออกทางซ้ายเป็นเท็จการแสดงออกที่ถูกต้องจะไม่ดำเนินการ

นำตัวอย่าง:

String str = null;

if(str!=null && !str.equals("")){  // the right expression will not execute

}

หากใช้&:

String str = null;

if(str!=null & !str.equals("")){  // the right expression will execute, and throw the NullPointerException 

}

อีกตัวอย่างหนึ่ง:

int x = 0;
int y = 2;
if(x==0 & ++y>2){
    System.out.print(“y=”+y);  // print is: y=3
}

int x = 0;
int y = 2;
if(x==0 && ++y>2){
    System.out.print(“y=”+y);  // print is: y=2
}

& สามารถใช้เป็นตัวดำเนินการบิตได้

&สามารถใช้เป็นANDตัวดำเนินการ Bitwise &&ไม่ได้

ตัวดำเนินการ bitwise AND "&" จะสร้าง 1 ถ้าหากบิตทั้งสองในตัวถูกดำเนินการเป็น 1 อย่างไรก็ตามถ้าบิตทั้งสองเป็น 0 หรือทั้งสองของบิตนั้นแตกต่างกันตัวดำเนินการนี้จะสร้าง 0 ให้แม่นยำขึ้น AND "&" ตัวดำเนินการส่งคืน 1 ถ้าหนึ่งในสองบิตใด ๆ เป็น 1 และจะส่งกลับ 0 ถ้าบิตใด ๆ เป็น 0 

จากหน้า wiki:

http://www.roseindia.net/java/master-java/java-bitwise-and.shtml


4

'&&': - เป็นตัวดำเนินการตรรกะและสร้างค่าบูลีนของจริงหรือเท็จขึ้นอยู่กับความสัมพันธ์เชิงตรรกะของการขัดแย้ง

ตัวอย่างเช่น: - Condition1 && Condition2

หากเงื่อนไข 1 เป็นเท็จดังนั้น (เงื่อนไข 1 && เงื่อนไข 2) จะเป็นเท็จเสมอนั่นคือสาเหตุที่ผู้ให้บริการลอจิคัลนี้รู้จักกันในชื่อ Short Circuit Operator เพราะไม่ได้ประเมินเงื่อนไขอื่น หาก Condition1 เป็นเท็จแสดงว่าไม่จำเป็นต้องประเมิน Condtiton2

ถ้า Condition1 เป็นจริงแล้ว Condition2 จะถูกประเมินถ้าเป็นจริงผลลัพธ์โดยรวมจะเป็นจริงมิฉะนั้นจะเป็นเท็จ

'&': - เป็น Bitwise AND Operator มันก่อให้เกิดหนึ่ง (1) ในการส่งออกถ้าทั้งสองบิตอินพุตเป็นหนึ่ง มิฉะนั้นจะสร้างศูนย์ (0)

ตัวอย่างเช่น:-

int a = 12; // การเป็นตัวแทนไบนารีของ 12 คือ 1100

int b = 6; // การแทนค่าฐานสองของ 6 คือ 0110

int c = (a & b); // การแทนค่าไบนารีของ (12 & 6) คือ 0100

ค่าของ c คือ 4

สำหรับการอ้างอิงอ้างอิงhttp://techno-terminal.blogspot.in/2015/11/difference-between-operator-and-operator.htmlนี้


3

&&และ||เรียกว่าผู้ประกอบการลัดวงจร เมื่อมีการใช้งานสำหรับ||- ถ้าตัวถูกดำเนินการแรกประเมินค่าtrueแล้วตัวถูกดำเนินการที่เหลือจะไม่ถูกประเมิน สำหรับ&&- ถ้าตัวถูกดำเนินการแรกประเมินไปfalseแล้วส่วนที่เหลือจะไม่ได้รับการประเมินเลย

ดังนั้นif (a || (++x > 0))ในตัวอย่างนี้ตัวแปร x trueจะไม่ได้รับเพิ่มขึ้นถ้าเป็น


3

ด้วย booleans ไม่มีความแตกต่างระหว่างทั้งสอง คุณสามารถสลับ && และ & หรือ || และ | และมันจะไม่เปลี่ยนผลลัพธ์ของการแสดงออกของคุณ

ความแตกต่างอยู่เบื้องหลังของข้อมูลที่กำลังถูกประมวลผล เมื่อคุณแสดงออกทางขวา "(a! = 0) & (b! = 0)" สำหรับ a = 0 และ b = 1 สิ่งต่อไปนี้จะเกิดขึ้น:

left side: a != 0 --> false
right side: b 1= 0 --> true
left side and right side are both true? --> false
expression returns false

เมื่อคุณเขียนนิพจน์(a != 0) && ( b != 0)เมื่อ a = 0 และ b = 1 เหตุการณ์ต่อไปนี้จะเกิดขึ้น:

a != 0 -->false
expression returns false

ขั้นตอนน้อยลงการประมวลผลที่น้อยลงการเขียนโค้ดที่ดีขึ้นโดยเฉพาะอย่างยิ่งเมื่อทำนิพจน์บูลีนจำนวนมากหรืออาร์กิวเมนต์ที่ซับซ้อน


2
มันจะเปลี่ยนผลลัพธ์โดยรวมของการแสดงออกถ้าตัวถูกดำเนินการมีผลข้างเคียง
มาร์ควิสแห่ง Lorne

3

นอกจาก && และ || เป็นการลัดวงจรพิจารณาความสำคัญของโอเปอเรเตอร์เมื่อผสมสองรูปแบบ ฉันคิดว่ามันจะไม่ปรากฏทันทีสำหรับทุกคนที่ result1 และ result2 มีค่าต่างกัน

boolean a = true;
boolean b = false;
boolean c = false;

boolean result1 = a || b && c; //is true;  evaluated as a || (b && c)
boolean result2 = a  | b && c; //is false; evaluated as (a | b) && c

0

& เป็นตัวดำเนินการระดับบิตและใช้สำหรับตรวจสอบเงื่อนไขทั้งสองเพราะบางครั้งเราจำเป็นต้องประเมินทั้งสองเงื่อนไข แต่ตัวดำเนินการเชิงตรรกะ && ไปที่เงื่อนไขที่ 2 เมื่อเงื่อนไขแรกให้จริง


0

คำตอบทั้งหมดคือgreatและดูเหมือนว่าจะnoมีคำตอบมากกว่านี้is needed แต่ฉันเพิ่งจะชี้ให้เห็นสิ่งที่&&ผู้ประกอบการเรียกdependent condition

ในนิพจน์ที่ใช้โอเปอเรเตอร์ && เงื่อนไข - เราจะเรียกสิ่งนี้ว่าdependent condition- อาจต้องมีเงื่อนไขอื่นที่จะเป็นจริงสำหรับการประเมินเงื่อนไขที่ต้องพึ่งพานั้นจะมีความหมาย

ในกรณีนี้ควรวางเงื่อนไขที่สัมพันธ์กันหลังจากตัวดำเนินการ && เพื่อป้องกันข้อผิดพลาด

(i != 0) && (10 / i == 2)พิจารณาการแสดงออก ขึ้นอยู่กับเงื่อนไขที่(10 / i == 2)จะต้องผู้ประกอบการเพื่อป้องกันไม่ให้เป็นไปได้ของการหารด้วยศูนย์appear after&&

ตัวอย่างอื่น (myObject != null) && (myObject.getValue() == somevaluse)

และอีกสิ่งหนึ่ง: &&และได้||รับการเรียกการประเมินผลการลัดวงจรเพราะอาร์กิวเมนต์ที่สองจะถูกดำเนินการหรือการประเมินอาร์กิวเมนต์ไม่ไปonly iffirstnot sufficedeterminevalueของexpression

ข้อมูลอ้างอิง: Java ™วิธีการโปรแกรม (Early Objects), Tenth Edition

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