Ảnh hưởng của một toán tử Bitwise trên một Boolean trong Java


118

Các toán tử bitwise được cho là di chuyển các biến và hoạt động trên chúng từng chút một. Trong trường hợp số nguyên, dài, ký tự, điều này có ý nghĩa. Các biến này có thể chứa đầy đủ các giá trị được thực thi theo kích thước của chúng.

Tuy nhiên, trong trường hợp boolean, một boolean chỉ có thể chứa hai giá trị. 1 = true hoặc 0 = false. Nhưng kích thước của boolean không được xác định. Nó có thể lớn bằng một byte hoặc nhỏ một chút.

Vậy tác dụng của việc sử dụng toán tử bitwise trên boolean là gì? JVM về cơ bản có dịch nó sang một toán tử logic bình thường và tiếp tục không? Nó có coi boolean như một thực thể bit đơn cho mục đích của hoạt động không? Hay kết quả là không xác định cùng với kích thước của boolean?


1
Tôi nghĩ bạn không thể sử dụng toán tử bitwise trên boolean. Chỉ trên con số. Tôi chắc chắn ~ sẽ không hoạt động, tôi không biết những gì về các nhà khai thác khác.
Martijn Courteaux

4
Bạn có thể sử dụng một số trong số chúng, chúng tôi vừa phát hiện ra một | được sử dụng trong mã kế thừa của chúng tôi. Chúng tôi đang xóa nó, nhưng mã này đã được biên dịch và hoạt động.
Daniel Bingham

9
Vì một cái bị đoản mạch còn cái kia thì không (xem câu trả lời của mobrule), trước khi bạn thay đổi dấu | đến || bạn có thể muốn đảm bảo rằng các biểu thức boolean tiếp theo không có bất kỳ tác dụng phụ nào mà lập trình viên ban đầu dự định sẽ luôn thực thi.
John M Gant

Câu trả lời:


122

Các toán tử &, ^|là toán tử bit khi toán hạng là kiểu tích phân nguyên thủy. Chúng là các toán tử logic khi các toán hạng là boolean và hành vi của chúng trong trường hợp thứ hai được chỉ định. Xem phần 15.22.2 của Đặc tả ngôn ngữ Java để biết thêm chi tiết.


57
Cụ thể, & và ^ và | là các toán tử boolean logic không ngắn mạch.
Ken

14
Đây là liên kết trực tiếp đến phần được đề cập ở trên: docs.oracle.com/javase/specs/jls/se7/html/…
Andy Thomas

Nếu điều trên là đúng, tại sao Ideone.com/oGSF7c lại đưa ra một ngoại lệ con trỏ null? Nếu |=toán tử là logic, chương trình sẽ không bao giờ chạy x.getValue()chỉ thị.
ikromm

1
@JohnKrommidas, x của bạn là null, đó là lý do tại sao bạn nhận được NullPointerException. Bạn cần phải khởi tạo nó.
Ben

4
@Ben, Như @Ken nói, logic không ngắn mạch, vì vậy phần thứ hai được đánh giá. Vì vậy, a || x.foo()là an toàn nếu x là null, nhưng a | x.foo()không. |=tuân theo các quy tắc tương tự như |.
Michael Smith

86

Sử dụng toán tử bitwise có thể tránh được hiện tượng đoản mạch:

boolean b = booleanExpression1() && booleanExpression2();
boolean b = booleanExpression1() & booleanExpression2();

Nếu được booleanExpression1()đánh giá false, thì
booleanExpression2()không được đánh giá trong trường hợp đầu tiên và
booleanExpression2()(và bất kỳ tác dụng phụ nào mà nó có thể có) được đánh giá trong trường hợp thứ hai,


2
Và hoạt động bitwise thực hiện thường nhanh hơn hoạt động ngắn mạch (miễn là việc đánh giá đơn giản)
rds 24/02

1
Các Bitwise &sẽ nhanh hơn, nhưng các cuộc gọi đến các chức năng thứ hai có thể được bỏ qua với việc sử dụng&&
NatNgs

20

Ngoài những gì được đề cập trong các câu trả lời khác, cần lưu ý rằng &&||có mức độ ưu tiên khác với &|.

Trích xuất từ bảng ưu tiên (với ưu tiên cao nhất ở trên cùng).

bitwise AND                 &
bitwise exclusive OR        ^
bitwise inclusive OR        |
logical AND                 &&
logical OR                  ||

Điều này có ý nghĩa gì với bạn?

Hoàn toàn không có gì, miễn là bạn bám vào chỉ &|hoặc chỉ &&||.

Tuy nhiên, vì |có mức độ ưu tiên cao hơn &&(trái ngược với ||mức độ ưu tiên thấp hơn), việc tự do trộn chúng có thể dẫn đến hành vi không mong muốn.

Vì vậy, a && b | c && dgiống như a && (b | c) && d,
trái ngược với a && b || c && dsẽ là (a && b) || (c && d).

Để chứng minh chúng không giống nhau, hãy xem xét một đoạn trích từ bảng sự thật:

a | b | c | d | (b|c) | (a&&b) | (c&&d) | a && (b|c) && d | (a&&b) || (c&&d)
F | T | T | T |   T   |   F    |    T   |         F       |        T
                                                  ^                ^
                                                  |- not the same -|

Nếu bạn muốn OR có mức độ ưu tiên cao hơn AND, bạn có thể sử dụng |&& cùng nhau, nhưng điều này không được khuyến khích.

Nhưng bạn thực sự nên đặt chúng trong ngoặc để làm rõ mức độ ưu tiên bất cứ khi nào sử dụng các ký hiệu khác nhau, tức là (a && b) || c(dấu ngoặc để làm rõ mức độ ưu tiên), a && b && c(không cần dấu ngoặc).


3

Ngay cả khi nó sẽ hiệu quả, bạn không nên làm điều đó. Các thông số ngôn ngữ chỉ xác định các toán tử bitwise khi cả hai toán hạng đều thuộc kiểu số nguyên nguyên thủy hoặc cả hai đều thuộc kiểu boolean. Tôi muốn nói đối với bất kỳ trường hợp nào khác, kết quả không được xác định:

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5228


Câu hỏi về boolean, không phải về nguyên thủy hay sự kết hợp giữa nguyên thủy và boolean.
talonx
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.