Sự khác biệt trong toán tử boolean: & vs && và | vs ||


Câu trả lời:


134

Đó là các toán tử bitwise AND và 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

Cảm ơn Carlos đã chỉ ra phần thích hợp trong Thông số ngôn ngữ Java ( 15.22.1 , 15.22.2 ) liên quan đến các hành vi khác nhau của toán tử dựa trên đầu vào của nó.

Thật vậy, khi cả hai đầu vào là boolean, các toán tử được coi là Toán tử logic Boolean và hoạt động tương tự như các toán tử Điều kiện-Và ( &&) và Điều kiện-Hoặc ( ||) ngoại trừ thực tế là chúng không ngắn mạch nên trong khi các toán tử sau là an toàn :

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

Đây không phải là:

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

"Đoản mạch" có nghĩa là người vận hành không nhất thiết phải kiểm tra tất cả các điều kiện. Trong các ví dụ trên, &&sẽ chỉ kiểm tra điều kiện thứ hai khi akhông null(nếu không thì toàn bộ câu lệnh sẽ trả về false và dù sao thì cũng sẽ rất khó để kiểm tra các điều kiện sau), do đó, câu lệnh của a.somethingsẽ không đưa ra ngoại lệ hoặc được coi là "an toàn . "

Các &nhà điều hành luôn kiểm tra mọi điều kiện trong mệnh đề, vì vậy trong các ví dụ trên, a.somethingcó thể được đánh giá khi athực chất là một nullgiá trị, nâng cao một ngoại lệ.


1
muốn làm rõ .. & sẽ trả về 1 chỉ nếu CẢ HAI là 1? Vậy 101 & 001 sẽ là 001? Đúng?
gideon

@giddy @Jonathon - Tôi đã cập nhật các giá trị của mình để thể hiện tốt hơn tình huống đó.
Justin Niessner

không đầy đủ: chúng cũng là toán tử LOGICAL (cho boolean).
user85421 25/10/10

1
@ Carlos- Không. Họ vẫn là những toán tử khôn ngoan. Chúng chỉ hoạt động giống như các toán tử logic không đoản mạch. Có một sự khác biệt.
Justin Niessner

4
và các toán tử logic không ngắn mạch là gì? Các toán tử & và | (do OP hỏi) là "Toán tử Bitwise nguyên" (JLS 15.22.1) "Toán tử logic Boolean" (JLS 15.22.2). Hay là Đặc tả ngôn ngữ Java sai về điều đó?
dùng85421

108

Tôi nghĩ bạn đang nói về ý nghĩa hợp lý của cả hai toán tử, ở đây bạn có một sơ yếu lý lịch:

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

Đánh giá ngắn mạch , đánh giá tối thiểu hoặc đánh giá McCarthy (sau John McCarthy) là ngữ nghĩa của một số toán tử Boolean trong một số ngôn ngữ lập trình trong đó đối số thứ hai chỉ được thực thi hoặc đánh giá nếu đối số đầu tiên không đủ để xác định giá trị của biểu thức: khi đối số đầu tiên của hàm AND cho giá trị false, giá trị tổng thể phải là false; và khi đối số đầu tiên của hàm OR được đánh giá là true, giá trị tổng thể phải là true.

Không an toàn có nghĩa là toán tử luôn kiểm tra mọi điều kiện trong mệnh đề, vì vậy trong các ví dụ trên, 1 / x có thể được đánh giá khi x thực tế là giá trị 0, tạo ra một ngoại lệ.


1
@Torres - Vui lòng mở rộng câu trả lời của bạn bằng cách giải thích "đoản mạch" và "an toàn". Ngoài ra là "độc quyền hoặc" và "logic không" cũng "không đoản mạch"? Và tại sao nó được gọi là "logic not" thay vì "boolean logic not"? Và tại sao "logic NOT" không được nhóm với "logic AND" và "logic OR"? Câu trả lời tốt nhưng cần làm việc.
tfmontague

@tfmontague, tôi đã giải thích ngắn mạch nghĩa là gì (bằng cách chỉnh sửa câu trả lời này) .. Đang chờ chỉnh sửa của tôi được "đồng nghiệp đánh giá".
Taslim Oseni

không đoản mạch là gì "không an toàn"? nó không phải là an toàn hơn sử dụng ngắn mạch? btw: bạn không thực sự giải thích thuật ngữ "ngắn mạch". nó có nghĩa là trên "không ngắn mạch", tất cả các bộ phận được đánh giá đầu tiên, sau đó hoạt động boolean được áp dụng, trong khi ngắn mạch, đánh giá bị dừng lại, khi biểu thức đầu tiên thỏa mãn điều kiện, như (a || b) sẽ không đánh giá b, nếu a đúng và phép toán or sẽ trả về true, bất kể b là gì.
SCI

26

Tôi biết có rất nhiều câu trả lời ở đây, nhưng tất cả đều có vẻ hơi khó hiểu. Vì vậy, sau khi thực hiện một số nghiên cứu từ hướng dẫn học Java oracle, tôi đã đưa ra ba tình huống khác nhau về thời điểm sử dụng && hoặc &. Ba trường hợplogic AND , bitwise ANDboolean AND .

Logical AND: Logic AND (hay còn gọi là AND có điều kiện) sử dụng toán tử && . Nó có nghĩa là ngắn mạch: nếu toán hạng bên trái là sai, thì toán hạng bên phải sẽ không được đánh giá.
Thí dụ:

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

Trong ví dụ trên, giá trị được in ra bảng điều khiển của x sẽ là 0, vì toán hạng đầu tiên trong câu lệnh if là sai, do đó java không cần tính toán (1 == ++ x) do đó x sẽ không được tính.

Bitwise AND: Bitwise AND sử dụng toán tử & . Nó được sử dụng để định dạng trước một hoạt động bitwise trên giá trị. Sẽ dễ dàng hơn nhiều để xem những gì đang xảy ra bằng cách xem hoạt động trên các số nhị phân, ví dụ:

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

Như bạn có thể thấy trong ví dụ, khi các biểu diễn nhị phân của số 5 và 12 được xếp thẳng hàng, sau đó AND được định dạng sẵn một chút sẽ chỉ tạo ra một số nhị phân trong đó cùng một chữ số trong cả hai số có 1. Do đó 0101 & 1100 == 0100. Trong số thập phân là 5 & 12 == 4.

Boolean AND: Bây giờ toán tử boolean AND hoạt động tương tự và khác với cả AND bit và AND logic. Tôi thích nghĩ về nó như là định dạng trước một chút AND giữa hai giá trị boolean (hoặc các bit), do đó nó sử dụng toán tử & . Các giá trị boolean cũng có thể là kết quả của một biểu thức logic.

Nó trả về một giá trị đúng hoặc sai, giống như AND logic, nhưng không giống AND logic, nó không bị đoản mạch. Lý do là để nó định dạng trước AND bitwise đó, nó phải biết giá trị của cả toán hạng trái và phải. Đây là một người yêu cũ:

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

Bây giờ khi câu lệnh if đó được chạy, biểu thức (1 == ++ x) sẽ được thực thi, ngay cả khi toán hạng bên trái là false. Do đó, giá trị được in ra cho x sẽ là 1 vì nó tăng dần.

Điều này cũng áp dụng cho Logical OR (||), bitwise OR (|), và boolean OR (|) Hy vọng điều này sẽ giải tỏa một số nhầm lẫn.


to preform that bitwise AND, it must know the value of both left and right operandsĐiều này nghe có vẻ không đúng với tôi. Để thực hiện một BITWISE ANDtoán hạng, bạn không cần phải biết toán hạng bên phải để có thể tìm ra kết quả nếu toán hạng bên trái là FALSE. Những gì bạn giải thích là đúng, nhưng lý do bạn nhà nước dường như không phải như vậy, với tôi ít nhất ..
Koray Tugay

7

Các toán tử && và || bị đoản mạch, nghĩa là họ sẽ không đánh giá biểu thức bên phải của mình nếu giá trị của biểu thức bên trái đủ để xác định kết quả.


7
-1 vì đã nói với OP những gì anh ấy đã biết và không trả lời câu hỏi mà anh ấy thực sự hỏi.
Alnitak

5

& và | cung cấp kết quả tương tự như && và || các toán tử. Sự khác biệt là chúng luôn đánh giá cả hai mặt của biểu thức trong đó là && và || ngừng đánh giá nếu điều kiện đầu tiên đủ để xác định kết quả.


1
Sai .... Vì &&nó đánh giá cả hai kết quả trong khi ||chỉ trả về nếu điều kiện đầu tiên là đúng.
Buhake Sindi

1
Huh? && chỉ đánh giá phía bên phải của biểu thức nếu phía bên trái đã đánh giá là true. Nếu không, nó ngừng đánh giá là sai lầm đầu tiên có nghĩa là kết quả không thể đúng. Xem jguru.com/faq/view.jsp?EID=16530
Brian Scott

1
( 2 & 4 )đánh giá đến false, trong khi ( 2 && 4 )đánh giá với true. Chính xác thì đó là kết quả như thế nào?
Piskvor rời tòa nhà

1
@Piskvor - không có trong Java! 2 & 4kết quả là một số nguyên, không phải là một boolean (0 trong trường hợp này). 2 && 4sẽ không biên dịch, && chỉ chấp nhận boolean. Java không cho phép trộn các phép toán luận và ints: zero không phải là false, falsekhông phải là không ...
user85421

1
@BuhakeSindi Sai. Vì &&nó chỉ đánh giá toán hạng thứ hai nếu toán hạng đầu tiên là true.
Marquis of Lorne,

2

Trong Java, các toán tử đơn &, |, ^,! phụ thuộc vào các toán hạng. Nếu cả hai toán hạng đều là int, thì một phép toán bit sẽ được thực hiện. Nếu cả hai đều là boolean, một phép toán "logic" được thực hiện.

Nếu cả hai toán hạng không khớp, lỗi thời gian biên dịch sẽ được đưa ra.

Các toán tử kép &&, || hoạt động tương tự với các đối số đơn lẻ của chúng, nhưng cả hai toán hạng phải là biểu thức điều kiện, ví dụ:

if ((a <0) && (b <0)) {...} hoặc tương tự, if ((a <0) || (b <0)) {...}

nguồn: lập trình java lang 4th ed



1

Có thể hữu ích khi biết rằng toán tử bitwise AND và bitwise OR luôn được đánh giá trước AND có điều kiện và OR có điều kiện được sử dụng trong cùng một biểu thức.

if ( (1>2) && (2>1) | true) // false!

1
ý bạn là ưu tiên của toán tử hơn là thứ tự đánh giá? Tôi không muốn thấy sự khác biệt ưu tiên được sử dụng trong mã thực. Sử dụng dấu ngoặc đơn thay vì toán tử bitwise cho mục đích này.
John Dvorak

1

&&; || là toán tử logic .... ngắn mạch

Nh & agrave; | là các toán tử logic boolean .... Không ngắn mạch

Chuyển đến sự khác biệt trong thực thi trên các biểu thức. Các toán tử bitwise đánh giá cả hai bên bất kể kết quả của phía bên trái. Nhưng trong trường hợp đánh giá biểu thức bằng các toán tử logic, việc đánh giá biểu thức bên phải phụ thuộc vào điều kiện bên trái.

Ví dụ:

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

Điều này sẽ in ra i = 26; j = 25, Vì điều kiện đầu tiên là sai, điều kiện bên phải bị bỏ qua vì kết quả là sai bất kể điều kiện bên phải. (ngắn mạch)

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

Nhưng, điều này sẽ in ra i = 26; j = 26,


0

Nếu một biểu thức liên quan đến toán tử Boolean & được đánh giá, cả hai toán hạng đều được đánh giá. Sau đó, toán tử & được áp dụng cho toán hạng.

Khi một biểu thức liên quan đến toán tử && được đánh giá, toán hạng đầu tiên được đánh giá. Nếu toán hạng đầu tiên đánh giá là false, thì việc đánh giá toán hạng thứ hai sẽ bị bỏ qua.

Nếu toán hạng đầu tiên trả về giá trị true thì toán hạng thứ hai được đánh giá. Nếu toán hạng thứ hai trả về giá trị true thì toán tử && sẽ được áp dụng cho toán hạng thứ nhất và thứ hai.

Tương tự cho | và ||.


0

Trong khi sự khác biệt cơ bản là &được sử dụng cho các hoạt động Bitwise chủ yếu trên long, inthoặc bytenơi nó có thể được sử dụng cho loại mặt nạ, kết quả có thể khác nhau ngay cả khi bạn sử dụng nó thay vì logic &&.

Sự khác biệt đáng chú ý hơn trong một số trường hợp:

  1. Đánh giá một số biểu thức tốn nhiều thời gian
  2. Việc đánh giá một trong các biểu thức chỉ có thể được thực hiện nếu biểu thức trước đó là đúng
  3. Các biểu thức có một số tác dụng phụ (dự định hoặc không)

Điểm đầu tiên là khá đơn giản, nó không gây ra lỗi, nhưng mất nhiều thời gian hơn. Nếu bạn có nhiều lần kiểm tra khác nhau trong một câu lệnh điều kiện, hãy đặt những phiếu kiểm tra rẻ hơn hoặc có nhiều khả năng bị lỗi hơn ở bên trái.

Đối với điểm thứ hai, hãy xem ví dụ này:

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

Điều này không thành công nullvì đánh giá biểu thức thứ hai tạo ra a NullPointerException. Toán tử logic &&là lười biếng, nếu toán hạng bên trái là sai, kết quả là sai bất kể toán hạng bên phải là gì.

Ví dụ cho điểm thứ ba - giả sử chúng ta có một ứng dụng sử dụng DB mà không có bất kỳ trình kích hoạt hoặc tầng nào. Trước khi xóa đối tượng Tòa nhà, chúng ta phải thay đổi tòa nhà của đối tượng Bộ thành một đối tượng khác. Cũng giả sử trạng thái hoạt động được trả về dưới dạng boolean (true = thành công). Sau đó:

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

Điều này đánh giá cả hai biểu thức và do đó thực hiện xóa tòa nhà ngay cả khi cập nhật bộ phận không thành công vì một số lý do. Với &&, nó hoạt động như dự định và nó dừng lại sau lần thất bại đầu tiên.

Đối với a || b, nó tương đương với !(!a && !b), nó dừng lại nếu ađúng, không cần giải thích thêm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.