Hubungan pendek operator logika Java


100

Himpunan mana yang mengalami hubung singkat, dan apa sebenarnya yang dimaksud dengan ekspresi kondisional kompleks yang mengalami korsleting?

public static void main(String[] args) {
  int x, y, z;

  x = 10;
  y = 20;
  z = 30;

  // T T
  // T F
  // F T
  // F F

  //SET A
  boolean a = (x < z) && (x == x);
  boolean b = (x < z) && (x == z);
  boolean c = (x == z) && (x < z);
  boolean d = (x == z) && (x > z);
  //SET B    
  boolean aa = (x < z) & (x == x);
  boolean bb = (x < z) & (x == z);
  boolean cc = (x == z) & (x < z);
  boolean dd = (x == z) & (x > z);

}

Jawaban:


244

The &&dan ||operator "short-circuit", yang berarti mereka tidak mengevaluasi sisi kanan jika tidak diperlukan.

The &dan |operator, bila digunakan sebagai operator logika, selalu mengevaluasi kedua belah pihak.

Hanya ada satu kasus korsleting untuk setiap operator, yaitu:

  • false && ...- tidak perlu mengetahui apa sisi kanannya karena hasilnya hanya bisa falseterlepas dari nilainya di sana
  • true || ...- tidak perlu mengetahui apa sisi kanannya karena hasilnya hanya bisa trueterlepas dari nilainya di sana

Mari bandingkan perilakunya dalam contoh sederhana:

public boolean longerThan(String input, int length) {
    return input != null && input.length() > length;
}

public boolean longerThan(String input, int length) {
    return input != null & input.length() > length;
}

2 versi menggunakan operator non-hubungan arus pendek &dan akan melempar NullPointerExceptionjika inputadalah null, tapi versi 1 akan kembali falsetanpa pengecualian.


9
Saya hanya ingin memperluas jawaban ini sedikit. Operator & = adalah singkatan dari x = x & ekspresi, dan oleh karena itu BUKAN hubung singkat. Hal yang sama berlaku untuk operator | =.
Stormcloud

11
Satu hal yang ingin saya soroti, | dan & adalah operator biner, sedangkan && dan || adalah operator bersyarat (logis). | dan & mengerjakan lebih dari sekadar boolean, sementara && dan || bekerja hanya pada boolean.
Mitos

1
Mereka tidak hanya tidak mengevaluasi ekspresi di sisi kanan, kodenya tidak dieksekusi agar ada yang perlu dievaluasi. Ini adalah titik kritis pemahaman jika efek samping akan dihasilkan.
mckenzm

@mckenzm Apa perbedaan antara dievaluasi dan dieksekusi?
Kronen

Eksekusi @Kronen dapat menghasilkan lebih dari evaluasi, dan menghasilkan efek samping, seperti pengecualian atau penundaan, saya akan membayar tidak relevan dengan contoh ini.
mckenzm

9

SET A menggunakan operator boolean hubungan pendek.

Apa arti 'hubung singkat' dalam konteks operator boolean adalah bahwa untuk satu set boolean b1, b2, ..., bn, versi hubung singkat akan menghentikan evaluasi segera setelah boolean pertama ini benar (|| ) atau salah (&&).

Sebagai contoh:

// 2 == 2 will never get evaluated because it is already clear from evaluating
// 1 != 1 that the result will be false.
(1 != 1) && (2 == 2)

// 2 != 2 will never get evaluated because it is already clear from evaluating
// 1 == 1 that the result will be true.
(1 == 1) || (2 != 2)

Harap tentukan bahwa ini kasusnya &&, ||bekerja secara berbeda dan akan menghentikan evaluasi pada operan pertama yang mengembalikan true;)
fge

1
Bahkan, harus benar-benar lengkap, semua &&, ||, &dan |mengevaluasi kiri ke kanan. Untuk satu set boolean b1, b2, ..., bn, versi hubung singkat akan menghentikan evaluasi jika boolean pertama ini benar ( ||) atau salah ( &&). Bah, prinsipnya ada;)
fge

@ Fge: Ya, tentu saja Anda benar. Definisi Anda lebih dari karakter saya. Saya telah memperbarui jawaban saya dengan kalimat di komentar Anda. Saya harap Anda tidak keberatan.
afrischke

Jangan khawatir, ilmu tidak ada nilainya jika tidak dibagikan.
fge

4

Korsleting berarti operator kedua tidak akan diperiksa jika operator pertama memutuskan hasil akhir.

Misalnya Ekspresi adalah: Benar || Salah

Dalam kasus ||, yang kita butuhkan hanyalah satu sisi untuk menjadi Benar. Jadi jika sisi kiri benar, tidak ada gunanya memeriksa sisi kanan, dan karenanya tidak akan diperiksa sama sekali.

Demikian pula, False && True

Dalam kasus &&, kita membutuhkan kedua sisi menjadi Benar. Jadi jika sisi kiri adalah False, tidak ada gunanya memeriksa sisi kanan, jawabannya pasti Salah. Dan karena itu tidak akan diperiksa sama sekali.


4
boolean a = (x < z) && (x == x);

Jenis ini akan korsleting, artinya jika (x < z)dievaluasi salah maka yang terakhir tidak dievaluasi, aakan salah, jika tidak &&juga akan dievaluasi (x == x).

& adalah operator bitwise, tetapi juga operator Boolean AND yang tidak mengalami hubungan arus pendek.

Anda dapat mengujinya dengan sesuatu sebagai berikut (lihat berapa kali metode dipanggil dalam setiap kasus):

public static boolean getFalse() {
    System.out.println("Method");
    return false;
}

public static void main(String[] args) {
    if(getFalse() && getFalse()) { }        
    System.out.println("=============================");        
    if(getFalse() & getFalse()) { }
}

-1 Jawaban Anda menunjukkan bahwa &ini hanya operator yang bijak, tetapi itu tidak benar. Ini juga merupakan operator boolean "atau".
Bohemian

@Bohemian: Terima kasih atas perhatiannya. true & falsemengevaluasi ke salah. Bisakah Anda menjelaskan "boolean" atau "operator" ini? Mungkin saya tidak mengerti apa yang ingin Anda katakan.
Bhesh Gurung

Maaf - maksud saya boolean AND, bukan OR! yaitu true & falsesintaks yang valid. -1 dihapus :)
Bohemian

4

Secara sederhana, korsleting berarti menghentikan evaluasi setelah Anda tahu bahwa jawabannya tidak dapat lagi berubah. Misalnya, jika Anda mengevaluasi rantai logika ANDdan Anda menemukan a FALSEdi tengah rantai itu, Anda tahu hasilnya akan salah, tidak peduli berapa nilai ekspresi lainnya dalam rantai tersebut. Hal yang sama berlaku untuk rangkaian ORs: setelah Anda menemukan a TRUE, Anda langsung mengetahui jawabannya, sehingga Anda dapat melewati evaluasi ekspresi lainnya.

Anda menunjukkan pada Java bahwa Anda ingin melakukan hubungan arus pendek dengan menggunakan &&alih- alih &dan ||sebagai gantinya |. Set pertama dalam posting Anda adalah hubungan arus pendek.

Perhatikan bahwa ini lebih dari sekadar upaya untuk menyimpan beberapa siklus CPU: dalam ekspresi seperti ini

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

korsleting berarti perbedaan antara operasi yang benar dan crash (dalam kasus di mana mystring adalah null).


2

Java menyediakan dua operator Boolean menarik yang tidak ditemukan di sebagian besar bahasa komputer lainnya. Versi sekunder dari AND dan OR ini dikenal sebagai operator logika hubung singkat . Seperti yang Anda lihat dari tabel sebelumnya, operator OR menghasilkan true ketika A benar, tidak peduli B adalah.

Demikian pula, operator AND menghasilkan false jika A salah, tidak peduli B adalah. Jika Anda menggunakan formulir ||dan &&, daripada formulir |dan &dari operator ini, Java tidak akan repot-repot mengevaluasi operan kanan saja. Ini sangat berguna ketika operan kanan bergantung pada yang kiri benar atau salah agar berfungsi dengan benar.

Misalnya, pecahan kode berikut menunjukkan bagaimana Anda dapat memanfaatkan evaluasi logika hubung singkat untuk memastikan bahwa operasi pembagian akan valid sebelum mengevaluasinya:

if ( denom != 0 && num / denom >10)

Karena bentuk hubungan pendek AND ( &&) digunakan, tidak ada risiko menyebabkan pengecualian run-time dari pembagian dengan nol. Jika baris kode ini ditulis menggunakan &versi tunggal AND, kedua sisi harus dievaluasi, menyebabkan pengecualian waktu proses ketika denomnol.

Ini adalah praktik standar untuk menggunakan bentuk hubung singkat dari AND dan OR dalam kasus yang melibatkan logika Boolean, meninggalkan versi karakter tunggal secara eksklusif untuk operasi bitwise. Namun, ada pengecualian untuk aturan ini. Misalnya, perhatikan pernyataan berikut:

 if ( c==1 & e++ < 100 ) d = 100;

Di sini, menggunakan satu &memastikan bahwa operasi kenaikan akan diterapkan eapakah csama dengan 1 atau tidak.


2

Logical OR: - mengembalikan nilai true jika setidaknya salah satu operand bernilai true. Kedua operan dievaluasi sebelum menerapkan operator OR.

Sirkuit Pendek ATAU: - jika operan sisi kiri mengembalikan nilai benar, ini mengembalikan nilai benar tanpa mengevaluasi operan sisi kanan.


2

Ada beberapa perbedaan antara operator &dan &&. Perbedaan yang sama berlaku untuk |dan ||. Yang penting yang paling diingat adalah bahwa &&adalah logis operator yang hanya berlaku untuk operan boolean, sedangkan &adalah bitwise operator yang berlaku untuk tipe integer serta boolean.

Dengan operasi logis, Anda dapat melakukan korsleting karena dalam kasus tertentu (seperti operan pertama &&makhluk false, atau operan pertama ||makhluk true), Anda tidak perlu mengevaluasi sisa ekspresi. Ini sangat berguna untuk melakukan hal-hal seperti memeriksanull sebelum mengakses file atau metode, dan memeriksa potensi nol sebelum membaginya. Untuk ekspresi kompleks, setiap bagian ekspresi dievaluasi secara rekursif dengan cara yang sama. Misalnya, dalam kasus berikut:

(7 == 8) || ( (1 == 3) && (4 == 4))

Hanya bagian yang ditekankan yang akan dievaluasi. Untuk menghitung ||, cek pertama jika 7 == 8ini true. Jika ya, sisi kanan akan dilewati seluruhnya. Sisi kanan hanya memeriksa jika 1 == 3ada false. Karena itu, 4 == 4tidak perlu diperiksa, dan seluruh ekspresi dievaluasi ke false. Jika sisi kiri true, misalnya 7 == 7alih-alih 7 == 8, seluruh sisi kanan akan dilewati karena seluruh ||ekspresi akan trueterlepas.

Dengan operasi bitwise, Anda perlu mengevaluasi semua operan karena Anda benar-benar hanya menggabungkan bit. Boolean secara efektif adalah bilangan bulat satu-bit di Java (terlepas dari bagaimana internal bekerja), dan itu hanya kebetulan bahwa Anda dapat melakukan hubungan arus pendek untuk operator bitwise dalam satu kasus khusus itu. Alasan mengapa Anda tidak dapat melakukan hubungan arus pendek pada integer umum &atau |operasi adalah bahwa beberapa bit mungkin aktif dan beberapa mungkin tidak aktif di salah satu operan. Sesuatu seperti 1 & 2menghasilkan nol, tetapi Anda tidak memiliki cara untuk mengetahui itu tanpa mengevaluasi kedua operan.


1
if(demon!=0&& num/demon>10)

Karena bentuk hubungan pendek dari AND (&&) digunakan, tidak ada risiko menyebabkan pengecualian waktu berjalan ketika demon bernilai nol.

Ref. Java 2 Edisi Kelima oleh Herbert Schildt

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.