Perbedaan operator boolean: & vs && dan | vs ||

Jawaban:

134

Itu adalah operator bitwise AND dan bitwise OR.

int a = 6; // 110
int b = 4; // 100

// Bitwise AND    

int c = a & b;
//   110
// & 100
// -----
//   100

// Bitwise OR

int d = a | b;
//   110
// | 100
// -----
//   110

System.out.println(c); // 4
System.out.println(d); // 6

Terima kasih kepada Carlos untuk menunjukkan bagian yang sesuai di Spesifikasi Bahasa Java ( 15.22.1 , 15.22.2 ) mengenai perbedaan perilaku operator berdasarkan masukannya.

Memang ketika kedua input adalah boolean, operator dianggap sebagai Operator Logis Boolean dan berperilaku mirip dengan operator Conditional-And ( &&) dan Conditional-Or ( ||) kecuali untuk fakta bahwa mereka tidak melakukan hubungan arus pendek jadi sementara yang berikut ini aman :

if((a != null) && (a.something == 3)){
}

Ini bukan:

if((a != null) & (a.something == 3)){
}

"Korsleting" berarti operator tidak perlu memeriksa semua kondisi. Dalam contoh di atas, &&akan memeriksa kondisi kedua hanya jika atidak null(jika tidak, seluruh pernyataan akan kembali salah, dan akan diperdebatkan untuk memeriksa kondisi berikut), jadi pernyataan a.somethingtidak akan menimbulkan pengecualian, atau dianggap "aman . "

The &Operator selalu meneliti setiap kondisi di klausa, sehingga pada contoh di atas, a.somethingdapat dievaluasi ketika apada kenyataannya merupakan nullnilai, menaikkan pengecualian.

Justin Niessner
sumber
1
ingin menjelaskan .. & akan mengembalikan 1 hanya jika KEDUA adalah 1? Jadi 101 & 001 akan menjadi 001? Baik?
gideon
@giddy @Jonathon - Saya memperbarui nilai-nilai saya untuk menunjukkan situasi itu dengan lebih baik.
Justin Niessner
tidak lengkap: mereka juga operator LOGIS (untuk boolean).
pengguna85421
1
@ Carlos- Tidak. Mereka masih operator bitwise. Mereka hanya berperilaku sama dengan operator logika non-short circuiting. Ada perbedaan.
Justin Niessner
4
dan apakah operator logika non-short circuiting? Operator & dan | (diminta oleh OP) adalah "Integer Bitwise Operator" (JLS 15.22.1) dan "Boolean Logical Operator" (JLS 15.22.2). Ataukah Spesifikasi Bahasa Java salah tentang itu?
pengguna85421
108

Saya pikir Anda sedang berbicara tentang arti logis dari kedua operator, di sini Anda memiliki resume tabel:

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

Evaluasi sirkuit pendek , evaluasi minimal, atau evaluasi McCarthy (setelah John McCarthy) adalah semantik dari beberapa operator Boolean dalam beberapa bahasa pemrograman di mana argumen kedua dijalankan atau dievaluasi hanya jika argumen pertama tidak cukup untuk menentukan nilai dari ekspresi: ketika argumen pertama dari fungsi AND bernilai false, nilai keseluruhan harus salah; dan ketika argumen pertama dari fungsi OR bernilai true, nilai keseluruhan harus benar.

Tidak Aman berarti operator selalu memeriksa setiap kondisi dalam klausa, jadi dalam contoh di atas, 1 / x dapat dievaluasi jika x sebenarnya adalah nilai 0, sehingga memunculkan pengecualian.

Torres
sumber
1
@Torres - Harap perluas jawaban Anda dengan menjelaskan "korsleting" dan "aman". Juga apakah "eksklusif atau" dan "tidak logis" juga "tidak mengalami hubungan arus pendek"? Dan mengapa ini disebut "logis bukan", bukan "boolean tidak logis"? Dan mengapa "logika NOT" tidak dikelompokkan dengan "logika AND" dan "logika OR"? Jawaban bagus tapi butuh kerja.
tfmontague
@tfmontague, saya sudah menjelaskan apa artinya korsleting (dengan mengedit jawaban ini) .. Menunggu hasil edit saya menjadi "peer review".
Taslim Oseni
apa yang "tidak aman" jika tidak mengalami hubungan arus pendek? bukankah seharusnya lebih aman daripada menggunakan sirkuit pendek? btw: Anda tidak benar-benar menjelaskan istilah "sirkuit pendek". ini berarti bahwa pada "bukan hubungan pendek" semua bagian dievaluasi terlebih dahulu, kemudian operasi boolean diterapkan, sedangkan pada hubungan pendek evaluasi dihentikan, ketika ekspresi pertama memenuhi kondisi, seperti (a || b) tidak akan evaluasi b, jika a benar dan operasi atau akan mengembalikan benar, tidak peduli apa b.
SCI
26

Saya tahu ada banyak jawaban di sini, tetapi semuanya tampak agak membingungkan. Jadi setelah melakukan penelitian dari panduan studi oracle Java, saya menemukan tiga skenario berbeda tentang kapan harus menggunakan && atau &. Ketiga skenario tersebut adalah logika AND , bitwise AND , dan boolean AND .

Logis AND: Logis AND (alias Conditional AND) menggunakan operator && . Ini berarti hubungan pendek: jika operan kiri salah, maka operan kanan tidak akan dievaluasi.
Contoh:

int x = 0;
if (false && (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); // "0"

Dalam contoh di atas, nilai yang dicetak ke konsol x akan menjadi 0, karena operan pertama dalam pernyataan if salah, maka java tidak perlu menghitung (1 == ++ x) sehingga x tidak akan dihitung.

Bitwise DAN: Bitwise AND menggunakan operator & . Ini digunakan untuk melakukan operasi bitwise pada nilai. Jauh lebih mudah untuk melihat apa yang terjadi dengan melihat operasi pada bilangan biner misalnya:

int a = 5;     //                    5 in binary is 0101
int b = 12;    //                   12 in binary is 1100
int c = a & b; // bitwise & preformed on a and b is 0100 which is 4

Seperti yang Anda lihat pada contoh, ketika representasi biner dari angka 5 dan 12 dibariskan, maka bitwise AND yang dibentuk sebelumnya hanya akan menghasilkan angka biner di mana digit yang sama pada kedua angka memiliki 1. Maka 0101 & 1100 == 0100. Yang dalam desimal adalah 5 & 12 == 4.

Boolean DAN: Sekarang operator boolean AND berperilaku serupa dan berbeda pada bitwise AND dan logika AND. Saya suka menganggapnya sebagai preforming sedikit DAN antara dua nilai boolean (atau bit), oleh karena itu menggunakan & operator. Nilai boolean juga bisa menjadi hasil dari ekspresi logis.

Ia mengembalikan nilai benar atau salah, seperti logika AND, tetapi tidak seperti logika AND, ia tidak dihubung pendek. Alasannya, adalah untuk membentuk sebelumnya bitwise AND, ia harus mengetahui nilai operan kiri dan kanan. Ini mantannya:

int x = 0;
if (false & (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); //"1"

Sekarang jika pernyataan if dijalankan, ekspresi (1 == ++ x) akan dieksekusi, meskipun operan kiri salah. Oleh karena itu nilai yang dicetak untuk x akan menjadi 1 karena bertambah.

Ini juga berlaku untuk Logical OR (||), bitwise OR (|), dan boolean OR (|) Semoga ini dapat menghilangkan kebingungan.

LynchburgExplorer
sumber
to preform that bitwise AND, it must know the value of both left and right operandsIni kedengarannya tidak benar bagi saya. Untuk melakukan sebuah BITWISE ANDAnda tidak perlu mengetahui operan kanan untuk dapat mengetahui hasil jika operan kiri adalah FALSE. Apa yang Anda jelaskan itu benar, tetapi alasan yang Anda nyatakan tampaknya tidak demikian, setidaknya bagi saya ..
Koray Tugay
7

Operator && dan || korsleting, artinya mereka tidak akan mengevaluasi ekspresi tangan kanannya jika nilai ekspresi tangan kiri cukup untuk menentukan hasilnya.

Tassos Bassoukos
sumber
7
-1 untuk memberi tahu OP apa yang sudah dia ketahui dan tidak menjawab pertanyaan yang sebenarnya dia tanyakan.
Alnitak
5

& dan | memberikan hasil yang sama dengan && dan || operator. Perbedaannya adalah mereka selalu mengevaluasi kedua sisi ekspresi dimana && dan || berhenti mengevaluasi jika kondisi pertama sudah cukup untuk menentukan hasil.

Brian Scott
sumber
1
Salah .... Karena &&itu mengevaluasi kedua hasil sementara ||mengembalikan hanya jika kondisi pertama benar.
Buhake Sindi
1
Hah? && hanya mengevaluasi sisi kanan ekspresi jika sisi kiri sudah bernilai true. Jika tidak, ia berhenti mengevaluasi karena kesalahan pertama secara tersirat berarti bahwa hasilnya tidak mungkin benar. Lihat jguru.com/faq/view.jsp?EID=16530
Brian Scott
1
( 2 & 4 )mengevaluasi ke false, sedangkan ( 2 && 4 )mengevaluasi ke true. Bagaimana sebenarnya hasil yang sama itu?
Piskvor meninggalkan gedung
1
@Piskvor - bukan di Java! 2 & 4menghasilkan integer, bukan boolean (nol dalam kasus ini). 2 && 4tidak akan mengkompilasi, && hanya menerima boolean. Java tidak mengizinkan pencampuran boolean dan int: nol bukan false, falsebukan nol ...
user85421
1
@Buhakeindi Salah. Untuk &&itu hanya mengevaluasi operan kedua jika operan pertama adalah true.
Marquis dari Lorne
2

Di Java, operator tunggal &, |, ^,! tergantung pada operannya. Jika kedua operan adalah int, maka operasi bitwise dilakukan. Jika keduanya boolean, operasi "logis" dilakukan.

Jika kedua operan tidak cocok, kesalahan waktu kompilasi akan muncul.

Operator ganda &&, || berperilaku mirip dengan satu mitranya, tetapi kedua operan harus berupa ekspresi bersyarat, misalnya:

if ((a <0) && (b <0)) {...} atau serupa, if ((a <0) || (b <0)) {...}

sumber: java programming lang 4th ed

aaron p.
sumber
1

Mungkin berguna untuk mengetahui bahwa operator bitwise AND dan bitwise OR selalu dievaluasi sebelum bersyarat AND dan bersyarat OR digunakan dalam ekspresi yang sama.

if ( (1>2) && (2>1) | true) // false!
alexmeia
sumber
1
maksud Anda prioritas operator daripada urutan evaluasi? Saya lebih suka tidak melihat perbedaan prioritas yang digunakan dalam kode sebenarnya. Gunakan tanda kurung daripada operator bitwise untuk tujuan ini.
John Dvorak
1

&&; || adalah operator logis .... korsleting

&; | adalah operator logika boolean .... Non-short circuit

Pindah ke perbedaan eksekusi pada ekspresi. Operator bitwise mengevaluasi kedua sisi terlepas dari hasil sisi kiri. Tetapi dalam kasus evaluasi ekspresi dengan operator logika, evaluasi ekspresi tangan kanan bergantung pada kondisi tangan kiri.

Sebagai contoh:

int i = 25;
int j = 25;
if(i++ < 0 && j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Ini akan mencetak i = 26; j = 25, Karena kondisi pertama salah, kondisi tangan kanan dilewati karena hasilnya salah terlepas dari kondisi sisi kanan. (korsleting)

int i = 25;
int j = 25;
if(i++ < 0 & j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Tapi, ini akan mencetak i = 26; j = 26,

Nickhil
sumber
0

Jika ekspresi yang melibatkan operator Boolean & dievaluasi, kedua operan dievaluasi. Kemudian operator & diterapkan ke operan.

Saat ekspresi yang melibatkan operator && dievaluasi, operan pertama dievaluasi. Jika operan pertama bernilai false, evaluasi operan kedua akan dilewati.

Jika operan pertama mengembalikan nilai true maka operan kedua dievaluasi. Jika operan kedua mengembalikan nilai true maka && operator kemudian diterapkan ke operan pertama dan kedua.

Mirip untuk | dan ||.

RishiKesh Pathak
sumber
0

Meskipun perbedaan dasarnya adalah yang &digunakan untuk operasi bitwise sebagian besar pada long, intatau di bytemana itu dapat digunakan untuk jenis topeng, hasilnya dapat berbeda bahkan jika Anda menggunakannya dan bukan logis &&.

Perbedaannya lebih terlihat dalam beberapa skenario:

  1. Mengevaluasi beberapa ekspresi memakan waktu
  2. Mengevaluasi salah satu ekspresi hanya dapat dilakukan jika ekspresi sebelumnya benar
  3. Ekspresi memiliki beberapa efek samping (disengaja atau tidak)

Poin pertama cukup jelas, tidak menyebabkan bug, tetapi membutuhkan lebih banyak waktu. Jika Anda memiliki beberapa pemeriksaan berbeda dalam satu pernyataan bersyarat, letakkan pemeriksaan yang lebih murah atau lebih cenderung gagal ke kiri.

Untuk poin kedua, lihat contoh ini:

if ((a != null) & (a.isEmpty()))

Ini gagal null, karena mengevaluasi ekspresi kedua menghasilkan a NullPointerException. Operator logika &&malas, jika operan kiri salah, hasilnya salah tidak peduli apapun operan kanannya.

Contoh untuk poin ketiga - katakanlah kita memiliki aplikasi yang menggunakan DB tanpa pemicu atau kaskade apa pun. Sebelum kita menghapus sebuah objek Gedung, kita harus mengubah sebuah gedung dari sebuah objek Departemen ke yang lain. Misalkan juga status operasi dikembalikan sebagai boolean (true = sukses). Kemudian:

if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))

Ini mengevaluasi kedua ekspresi dan dengan demikian melakukan penghapusan gedung bahkan jika pembaruan departemen gagal karena beberapa alasan. Dengan&& , itu berfungsi sebagaimana mestinya dan berhenti setelah kegagalan pertama.

Adapun a || b, itu setara dengan !(!a && !b), berhenti jika abenar, tidak perlu penjelasan lagi.

Vlasec
sumber