Tại sao chúng ta thường sử dụng | | hơn | Sự khác biệt là gì?


219

Tôi chỉ tự hỏi tại sao chúng ta thường sử dụng logic HOẶC ||giữa hai booleans không theo bit |, mặc dù cả hai đều hoạt động tốt.

Ý tôi là, hãy nhìn vào những điều sau đây:

if(true  | true)  // pass
if(true  | false) // pass
if(false | true)  // pass
if(false | false) // no pass
if(true  || true)  // pass
if(true  || false) // pass
if(false || true)  // pass
if(false || false) // no pass

Chúng ta có thể sử dụng |thay vì ||? Điều tương tự với &&&.


16
Hầu hết mọi người quên điều đó | là một toán tử boolean không ngắn mạch ngoài việc là một toán tử bitwise.
John Meagher

1
Chi tiết về sự khác biệt là trong JLS. Xem java.sun.com/docs/books/jls/third_edition/html/ Kẻ
John Meagher

64
Chúng không giống nhau. Vui lòng kiểm tra các hướng dẫn về chúng đặc biệt là đánh giá ngắn mạch và đánh giá háo hức . ||&&ngắn mạch trong khi |&đang háo hức.
Hovercraft Full Of Eels

4
Vì tò mò, trong trường hợp nào bạn thực sự muốn sử dụng các phiên bản không ngắn? Tôi gần như luôn luôn nhìn thấy &&||, nhưng không bao giờ & |. Nếu bạn đang làm một cái gì đó phụ thuộc vào tác dụng phụ, tôi không hiểu tại sao bạn lại sử dụng thứ gì đó giống như (a & b | c)ai đó có thể dễ dàng nghĩ rằng "Tôi có thể tối ưu hóa điều này bằng cách sử dụng các phiên bản ngắn gọn."
Mike Bailey

2
Và, tất nhiên, họ có quyền ưu tiên khác nhau.
Licks nóng

Câu trả lời:


349

Nếu bạn sử dụng ||&&các biểu mẫu, thay vì |&các biểu mẫu của các toán tử này, Java sẽ không bận tâm để đánh giá toán hạng bên tay phải.

Đó là vấn đề nếu bạn muốn rút ngắn đánh giá hay không - hầu hết thời gian bạn muốn.

Một cách tốt để minh họa lợi ích của ngắn mạch sẽ là xem xét ví dụ sau.

Boolean b = true;
if(b || foo.timeConsumingCall())
{
   //we entered without calling timeConsumingCall()
}

Một lợi ích khác, như Jeremy và Peter đã đề cập, đối với ngắn mạch là kiểm tra tham chiếu null:

if(string != null && string.isEmpty())
{
    //we check for string being null before calling isEmpty()
}

thêm thông tin


115
Ví dụ kinh điển làfoo != null && foo.hasBar()
Jeremy

1
Nếu bạn thêm vào về ngoại lệ tham chiếu null có thể sử dụng | từ bình luận của @ Jeremy thì đây là câu trả lời tuyệt vời.
Peter Kelly

Cũng nhớ rằng && và || có nghĩa là một lệnh rẽ nhánh ở cấp mã máy (hãy nhớ rằng các nhánh có thể gây ra sự đánh giá sai về nhánh), vì vậy nếu bạn siêu phàm về hiệu suất thì chỉ sử dụng chúng khi chúng thực sự được yêu cầu ( foo != null && foo.hasBar()) hoặc nhanh hơn ( b || foo.timeConsumingCall()). 99% các nhà phát triển không cần phải lo lắng về mức độ tối ưu hóa vi mô này.
Jonathan Dickinson

3
Tôi ngạc nhiên không có ai đề cập khi bạn muốn sử dụng |. Kịch bản phổ biến nhất mà tôi sử dụng là khi một biến được sửa đổi trong kiểm tra như (j> 3 | ++ i> 3) hoặc (++ i> 3 | modifyingGlobalAmongOtherThings () = true). Không quá phổ biến mặc dù.
AndSoYouCode

8
Một ví dụ kinh điển khác là string == null || string.isEmpty();)
Peter Lawrey

83

| không thực hiện đánh giá ngắn mạch trong các biểu thức boolean. ||sẽ ngừng đánh giá nếu toán hạng đầu tiên là đúng, nhưng |sẽ không.

Ngoài ra, |có thể được sử dụng để thực hiện thao tác bitwise-OR trên các giá trị byte / short / int / long. ||không thể.


Cung cấp một câu trả lời đầy đủ và tôi sẽ chấp nhận nó. Cho đến nay bạn là người đầu tiên chọn khía cạnh này của nó.
John Meagher

Thiếu khía cạnh bitwise của |
John Meagher

63

Vì vậy, chỉ để xây dựng các câu trả lời khác với một ví dụ, đoản mạch là rất quan trọng trong các kiểm tra phòng thủ sau:

if (foo == null || foo.isClosed()) {
    return;
}

if (bar != null && bar.isBlue()) {
    foo.doSomething();
}

Sử dụng |&thay vào đó có thể dẫn đến NullPointerExceptionviệc bị ném ở đây.


Nếu bạn đã áp dụng mẫu NullObject thì nó sẽ không (hay đúng hơn là phủ nhận câu trả lời). Ngoài ra, tôi muốn kiểm tra xem foo có màu xanh hay không là một cái gì đó bên trong foo. Nếu nó màu xanh, thì làm gì đó không nên làm gì.
nicodemus13

@ nicodemus13 - điểm tốt, mặc dù mẫu Null Object đôi khi chỉ được mong muốn và cơ thể có thể là một cái gì đó khác với lời kêu gọi khác foo. "Ví dụ kinh điển" của Peter Lawrey là tốt nhất.
Paul Bellora

@Khan: Vâng, tôi khá là ngoan ngoãn và đối tượng Null không phải lúc nào cũng phù hợp. Tôi chỉ có thói quen tái cấu trúc mọi thứ một cách có ý thức. Không có gì đặc biệt sai với câu trả lời của bạn.
nicodemus13

39

Hợp lý ||&&kiểm tra phía bên tay phải chỉ khi cần thiết. Các |&kiểm tra cả hai bên mọi lúc.

Ví dụ:

int i = 12;
if (i == 10 & i < 9) // It will check if i == 10 and if i < 9
...

Viết lại:

int i = 12;
if (i == 10 && i < 9) // It will check if i == 10 and stop checking afterward because i != 10
...

Một vi dụ khac:

int i = 12;
if (i == 12 | i > 10) // It will check if i == 12 and it will check if i > 10
...

Viết lại:

int i = 12;
if (i == 12 || i > 10) // It will check if i == 12, it does, so it stops checking and executes what is in the if statement
...

18

Cũng nhận thấy một cạm bẫy phổ biến: Các nhà khai thác không lười biếng được ưu tiên hơn những người lười biếng, vì vậy:

boolean a, b, c;
a || b && c; //resolves to a || (b && c)
a | b && c; //resolves to (a | b) && c

Cẩn thận khi trộn chúng.


15

Ngoài việc đoản mạch, một điều khác cần lưu ý là thực hiện thao tác logic bitwise trên các giá trị có thể khác 0 hoặc 1 có ý nghĩa rất khác so với logic có điều kiện. Mặc dù USUALLY giống nhau cho |||, với &&&bạn nhận được kết quả rất khác nhau (ví dụ: 2 & 40 / false trong khi 2 && 4là 1 / true).

Nếu thứ bạn nhận được từ một hàm thực sự là một mã lỗi và bạn đang kiểm tra mức không 0, thì điều này có thể khá quan trọng.

Đây không phải là một vấn đề trong Java khi bạn phải đánh máy một cách rõ ràng để boolean hoặc so sánh với 0 hoặc tương tự, nhưng trong các ngôn ngữ khác có cú pháp tương tự (C / C ++ et al) thì có thể khá khó hiểu.

Ngoài ra, lưu ý rằng & và | chỉ có thể áp dụng cho các giá trị kiểu số nguyên và không phải mọi thứ có thể tương đương với kiểm tra boolean. Một lần nữa, trong các ngôn ngữ không phải là Java, có khá nhiều thứ có thể được sử dụng như một boolean với một != 0so sánh ngầm (con trỏ, float, các đối tượng với một operator bool(), v.v.) và các toán tử bitwise hầu như luôn vô nghĩa trong các bối cảnh đó.


3
Tôi vui mừng vì ít nhất có ai đó đã đề cập đến toàn bộ mục đích tồn tại của các nhà khai thác bitwise.
ulidtko

9

Thời gian duy nhất bạn sẽ sử dụng |hoặc &thay thế ||hoặc &&là khi bạn có các biểu thức boolean rất đơn giản và chi phí cắt ngắn (tức là một nhánh) lớn hơn thời gian bạn tiết kiệm bằng cách không đánh giá các biểu thức sau này.

Tuy nhiên, đây là một tối ưu hóa vi mô hiếm khi xảy ra ngoại trừ trong mã cấp thấp nhất.


1
Sẽ rất thú vị nếu trình biên dịch thực hiện điều này tự động trong một số trường hợp.
starblue

Có lẽ JIT có thể, nhưng trình biên dịch có xu hướng chỉ giải quyết các tối ưu hóa đơn giản.
Peter Lawrey

2
Có, tôi cũng đã thấy tình huống trong đó | nhanh hơn đáng kể so với chi phí chung của | |, đặc biệt là trên các CPU không có hoặc dự đoán nhánh giới hạn. Nó hiếm nhưng không nghe thấy. Một trong những đồng nghiệp của tôi đã tham gia vào một cuộc chiến hoàn nguyên trong một số mã với một nhà thầu vì anh ta (chính xác) đang sử dụng | và nhà thầu cứ nghĩ đó là "sai."
fluffy

4
@Fluffy, đạo đức của câu chuyện là nếu bạn làm điều gì đó khó khăn, nó cần bình luận về lý do tại sao bạn làm điều này hoặc nỗ lực của bạn có thể bị lãng phí sau này. ;)
Peter Lawrey

1
Vâng, cuối cùng anh ấy đã thêm một nhận xét (theo đề nghị của tôi về cách làm cho nhà thầu ngừng 'sửa chữa' nó), và tất cả đều tốt.
lông mịn

8

| | là logic hoặc toán tử trong khi | là bitwise hoặc toán tử.

boolean a = true;
boolean b = false;

if (a || b) {
}

int a = 0x0001;
a = a | 0x0002;

1
Thiếu điều đó | cũng là một toán tử boolean không ngắn mạch.
John Meagher

2
@ John Meagher: Điều đó là ngầm, vì nó là bitwise .
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

@ L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ làm thế nào bạn làm cho tên của bạn phong cách khác nhau trong hồ sơ của bạn?
UdayKiran Pulipati

8

một | b: đánh giá b trong mọi trường hợp

một | | b: chỉ đánh giá b nếu a đánh giá sai


7

Ngoài ra thực tế là | là toán tử bitwise: || là một toán tử ngắn mạch - khi một phần tử sai, nó sẽ không kiểm tra các phần tử khác.

 if(something || someotherthing)
 if(something | someotherthing)

nếu có gì đó ĐÚNG, | | sẽ không đánh giá một số thứ khác, trong khi | sẽ làm. Nếu các biến trong câu lệnh if của bạn thực sự là các lệnh gọi hàm, sử dụng | | có thể tiết kiệm rất nhiều hiệu suất.


Tại sao bạn sẽ sử dụng | trong một câu lệnh if. | | là boolean, | không phải, | sẽ chỉ là boolean nếu bạn đã làm việc trên hai giá trị boolean.
FlySwat

Đây là câu trả lời đầu tiên để có được tất cả.
John Meagher

Câu trả lời này không chính xác. Nếu một cái gì đó là FALSE, cả hai toán tử sẽ chuyển sang toán hạng tiếp theo. Sự khác biệt chỉ phát sinh khi toán hạng đầu tiên là đúng.
Michael Myers

Để xấu nó có một ví dụ hoàn toàn vô lý.
FlySwat

Tôi không biết tại sao mọi người sẽ sử dụng | hoặc & trong một câu lệnh if để so sánh boolean đơn giản, nhưng nó hoàn toàn hợp pháp và tôi thực sự đã thấy các ví dụ về điều đó khi tôi bắt đầu học lập trình.
Michael Stum

3
| is the binary or operator

|| is the logic or operator

2
Thiếu điều đó | cũng là một toán tử boolean không ngắn mạch.
John Meagher

3

Các toán tử ||&&được gọi là toán tử có điều kiện , trong khi |&được gọi là toán tử bitwise . Họ phục vụ các mục đích khác nhau.

Toán tử điều kiện chỉ hoạt động với các biểu thức đánh giá tĩnh booleanở cả hai bên trái và phải.

Toán tử bitwise hoạt động với bất kỳ toán hạng số nào.

Nếu bạn muốn thực hiện so sánh logic, bạn nên sử dụng các toán tử có điều kiện , vì bạn sẽ thêm một số loại an toàn cho mã của mình.


Um, |&cũng là nhà khai thác có điều kiện. Xin vui lòng xem các liên kết trong bình luận của tôi đến bài viết gốc.
Hovercraft Full Of Eels

@Hovercraft Full Of Eels: Biểu đồ đó hơi sai lệch; nó gọi chúng là các toán tử có điều kiện CHỈ trong bối cảnh các giá trị boolean, trong đó chúng tương đương về mặt toán học với các toán tử logic háo hức. Khi bạn bắt đầu xử lý những thứ có giá trị khác 0 hoặc 1 hoặc giá trị dấu phẩy động hoặc con trỏ hoặc bất cứ thứ gì, phép so sánh bị phá vỡ.
fluffy

@fluffy: không có gì sai lệch về biểu đồ vì cuộc thảo luận chỉ nói về các toán tử boolean. Rằng |&có thể được sử dụng như các toán tử bit-khôn ngoan là một vấn đề hoàn toàn riêng biệt.
Hovercraft Full Of Eels

1
Sẽ chính xác hơn khi đề cập đến chúng như các toán tử bit khôn ngoan được sử dụng trên các giá trị boolean chứ không phải các toán tử boolean. Chúng chỉ HAPPEN tương đương về mặt toán học khi chỉ có một bit duy nhất.
fluffy

2

Một lưu ý phụ: Java có | = nhưng không phải là || =

Một ví dụ về thời điểm bạn phải sử dụng | | là khi biểu thức đầu tiên là một thử nghiệm để xem liệu biểu thức thứ hai có nổ tung không. ví dụ: Sử dụng một | trong trường hợp sau hte có thể dẫn đến một NPE.

public static boolean isNotSet(String text) {
   return text == null || text.length() == 0;
}

2

Các câu trả lời khác đã thực hiện tốt việc bao gồm sự khác biệt về chức năng giữa các toán tử, nhưng các câu trả lời có thể áp dụng cho mọi ngôn ngữ có nguồn gốc C duy nhất tồn tại ngày nay. Câu hỏi được gắn thẻvà vì vậy tôi sẽ cố gắng trả lời cụ thể và kỹ thuật cho ngôn ngữ Java.

&|có thể là Toán tử bitwise Integer hoặc Toán tử logic Boolean. Cú pháp của các toán tử bitwise và logic ( §15,22 ) là:

AndExpression:
  EqualityExpression 
  AndExpression & EqualityExpression

ExclusiveOrExpression:
  AndExpression 
  ExclusiveOrExpression ^ AndExpression

InclusiveOrExpression:
  ExclusiveOrExpression 
  InclusiveOrExpression | ExclusiveOrExpression

Cú pháp cho EqualityExpressionđược định nghĩa trong §15,21 , yêu cầu RelationalExpressionđược xác định trong §15.20 , lần lượt yêu cầu ShiftExpressionReferenceTypeđược xác định trong §15.19§4.3 , tương ứng. ShiftExpressionyêu cầu AdditiveExpressionđược xác định trong §15,18 , tiếp tục đi sâu vào, xác định số học cơ bản, toán tử đơn nguyên, v.v. ReferenceTypeđi sâu vào tất cả các cách khác nhau để biểu diễn một loại. (Mặc dù ReferenceTypekhông bao gồm các kiểu nguyên thủy, định nghĩa về các kiểu nguyên thủy cuối cùng là bắt buộc, vì chúng có thể là kiểu thứ nguyên cho một mảng, một ReferenceType.)

Các toán tử Bitwise và Logical có các thuộc tính sau:

  • Các toán tử này có quyền ưu tiên khác nhau, với &quyền ưu tiên cao nhất và |quyền ưu tiên thấp nhất.
  • Mỗi toán tử này được liên kết trái cú pháp (mỗi nhóm từ trái sang phải).
  • Mỗi toán tử là giao hoán nếu các biểu thức toán hạng không có tác dụng phụ.
  • Mỗi toán tử là liên kết.
  • Các toán tử bitwise và logic có thể được sử dụng để so sánh hai toán hạng loại hoặc hai toán hạng loại boolean. Tất cả các trường hợp khác dẫn đến một lỗi thời gian biên dịch.

Sự khác biệt giữa việc toán tử đóng vai trò là toán tử bitwise hay toán tử logic phụ thuộc vào việc toán hạng có "chuyển đổi thành kiểu tích phân nguyên thủy" ( §4.2 ) hay nếu chúng thuộc loại booleanhoặc Boolean( §5.1.8 ).

Nếu các toán hạng là loại tích phân, thì việc thăng cấp số nhị phân ( §5.6.2 ) được thực hiện trên cả hai toán hạng, để lại cả hailong hoặc ints cho hoạt động. Kiểu của hoạt động sẽ là loại toán hạng (được thăng cấp). Tại thời điểm đó, &sẽ là bitwise AND, ^sẽ độc quyền bitwise OR và |sẽ được bao gồm bitwise OR. ( §15.22.1 )

Nếu các toán hạng là booleanhoặc Boolean, các toán hạng sẽ phải chuyển đổi unboxing nếu cần thiết ( §5.1.8 ), và loại hoạt động sẽ là boolean. &sẽ dẫn đến truenếu cả hai toán hạng là true, ^sẽ dẫn đến truenếu cả hai toán hạng khác nhau và| sẽ dẫn đến truenếu một toán hạng là true. ( §15.22.2 )

Ngược lại, && là "Toán tử có điều kiện và" ( §15,23 ) và ||là "Toán tử có điều kiện-hoặc" §15.24 ). Cú pháp của chúng được định nghĩa là:

ConditionalAndExpression:
  InclusiveOrExpression 
  ConditionalAndExpression && InclusiveOrExpression

ConditionalOrExpression:
  ConditionalAndExpression 
  ConditionalOrExpression || ConditionalAndExpression

&& giống như & , ngoại trừ việc nó chỉ đánh giá toán hạng bên phải nếu toán hạng bên trái là true. ||giống như |, ngoại trừ việc nó chỉ đánh giá toán hạng bên phải nếu toán hạng bên trái là false.

Có điều kiện-Và có các thuộc tính sau:

  • Toán tử có điều kiện và toán tử được liên kết từ trái sang phải (nhóm này từ trái sang phải).
  • Toán tử có điều kiện và hoàn toàn liên quan đến cả tác dụng phụ và giá trị kết quả. Đó là, đối với bất kỳ biểu thức a, bc, đánh giá của biểu thức ((a) && (b)) && (c)tạo ra kết quả tương tự, với các tác dụng phụ tương tự xảy ra theo thứ tự, như đánh giá của biểu thức (a) && ((b) && (c)).
  • Mỗi toán hạng của toán tử có điều kiện và phải có kiểu booleanhoặc hoặc Booleanxảy ra lỗi thời gian biên dịch.
  • Kiểu của một điều kiện - và luôn luôn là biểu thức boolean.
  • Trong thời gian chạy, biểu thức toán hạng bên trái được đánh giá đầu tiên; nếu kết quả có loại Boolean, nó phải chịu chuyển đổi unboxing ( §5.1.8 ).
  • Nếu giá trị kết quả là false, giá trị của biểu thức có điều kiện và và biểu thức falsetoán hạng bên phải không được ước tính.
  • Nếu giá trị của toán hạng bên trái là true, thì biểu thức bên phải được ước tính; nếu kết quả có loại Boolean, nó phải chịu chuyển đổi unboxing ( §5.1.8 ). Giá trị kết quả trở thành giá trị của điều kiện-và biểu thức.
  • Do đó, &&tính kết quả tương tự như &trên booleantoán hạng. Nó chỉ khác ở chỗ biểu thức toán hạng bên phải được đánh giá có điều kiện chứ không phải luôn luôn.

Có điều kiện-Hoặc có các thuộc tính sau:

  • Toán tử có điều kiện - hoặc toán tử là liên kết trái cú pháp (nhóm này từ trái sang phải).
  • Toán tử có điều kiện hoặc hoàn toàn liên quan đến cả tác dụng phụ và giá trị kết quả. Đó là, đối với bất kỳ biểu thức a, bc, đánh giá của biểu thức ((a) || (b)) || (c)tạo ra kết quả tương tự, với các tác dụng phụ tương tự xảy ra theo thứ tự, như đánh giá của biểu thức (a) || ((b) || (c)).
  • Mỗi toán hạng của toán tử có điều kiện hoặc phải có kiểu booleanhoặc hoặc Booleanxảy ra lỗi thời gian biên dịch.
  • Kiểu của một điều kiện-hoặc biểu thức luôn luôn là boolean .
  • Trong thời gian chạy, biểu thức toán hạng bên trái được đánh giá đầu tiên; nếu kết quả có loại Boolean, nó phải chịu chuyển đổi unboxing ( §5.1.8 ).
  • Nếu giá trị kết quả là true, giá trị của biểu thức có điều kiện làtrue và biểu thức toán hạng bên phải không được ước tính.
  • Nếu giá trị của toán hạng bên trái là false, thì biểu thức bên phải được ước tính; nếu kết quả có loại Boolean, nó phải chịu chuyển đổi unboxing ( §5.1.8 ). Giá trị kết quả trở thành giá trị của biểu thức có điều kiện-hoặc.
  • Do đó, ||tính kết quả tương tự như |trên booleanhoặc Booleantoán hạng. Nó chỉ khác ở chỗ biểu thức toán hạng bên phải được đánh giá có điều kiện chứ không phải luôn luôn.

Nói tóm lại, như @JohnMeagher đã nhiều lần chỉ ra trong các bình luận, &|trên thực tế, các toán tử boolean không ngắn mạch trong trường hợp cụ thể của toán hạng là booleanhoặc Boolean. Với các thực hành tốt (nghĩa là: không có tác dụng phụ), đây là một sự khác biệt nhỏ. Tuy nhiên, khi các toán hạng không phải booleanlà s hoặc Booleans, các toán tử hoạt động rất khác nhau: các phép toán bit và logic đơn giản là không so sánh tốt ở mức độ cao của lập trình Java.


2

1). (Biểu thức1 | biểu thức2), | toán tử sẽ đánh giá biểu thức2 bất kể kết quả của biểu thức1 là đúng hay sai.

Thí dụ:

class Or 
{
    public static void main(String[] args) 
    {
        boolean b=true;

        if (b | test());
    }

    static boolean test()
    {
        System.out.println("No short circuit!");
        return false;
    }
}

2). (Biểu thức1 | | biểu thức2), | | toán tử sẽ không đánh giá biểu thức2 nếu biểu thức1 là đúng.

Thí dụ:

class Or 
{
    public static void main(String[] args) 
    {
        boolean b=true;

        if (b || test())
        {
            System.out.println("short circuit!");
        }
    }

    static boolean test()
    {
        System.out.println("No short circuit!");
        return false;
    }
}

1

| | trả về một giá trị boolean bằng cách OR'ing hai giá trị (Đó là lý do tại sao nó được gọi là logic hoặc)

I E:

if (A || B) 

Sẽ trả về true nếu A hoặc B là true hoặc false nếu cả hai đều sai.

| là một toán tử thực hiện một hoạt động bitwise trên hai giá trị. Để hiểu rõ hơn về hoạt động của bitwise, bạn có thể đọc tại đây:

http://en.wikipedia.org/wiki/Bitwise_operation


1

Một điểm khác biệt chính là | | và && trưng bày "ngắn mạch", do đó RHS sẽ chỉ được đánh giá nếu cần.

Ví dụ

if (a || b) {
    path1...
} else {
    path2..
}

Ở trên nếu a đúng thì b sẽ không được kiểm tra và path1 được thực thi. Nếu | đã được sử dụng thì cả hai bên sẽ được đánh giá ngay cả khi 'a' là đúng.

Xem ở đâyở đây , để biết thêm một chút thông tin.

Hi vọng điêu nay co ich.


1

Không ngắn mạch có thể hữu ích. Đôi khi bạn muốn chắc chắn rằng hai biểu thức đánh giá. Ví dụ: giả sử bạn có một phương pháp loại bỏ một đối tượng khỏi hai danh sách riêng biệt. Bạn có thể muốn làm một cái gì đó như thế này:

class foo {

    ArrayList<Bar> list1 = new ArrayList<Bar>();
    ArrayList<Bar> list2 = new ArrayList<Bar>();

    //Returns true if bar is removed from both lists, otherwise false.
    boolean removeBar(Bar bar) {
        return (list1.remove(bar) & list2.remove(bar));
    }
}

Nếu phương thức của bạn thay vì sử dụng toán hạng có điều kiện, nó sẽ không thể xóa đối tượng khỏi danh sách thứ hai nếu danh sách đầu tiên trả về sai.

//Fails to execute the second remove if the first returns false.
boolean removeBar(Bar bar) {
    return (list1.remove(bar) && list2.remove(bar));
}

Nó không hữu ích một cách đáng kinh ngạc, và (như với hầu hết các nhiệm vụ lập trình), bạn có thể đạt được nó bằng các phương tiện khác. Nhưng nó là một trường hợp sử dụng cho toán hạng bitwise.


1

Sự khác biệt cơ bản giữa chúng là | đầu tiên chuyển đổi các giá trị thành nhị phân sau đó thực hiện thao tác bit khôn ngoan hoặc hoạt động. Trong khi đó, || không chuyển đổi dữ liệu thành nhị phân và chỉ thực hiện hoặc biểu thức ở trạng thái ban đầu.

int two = -2; int four = -4;
result = two | four; // bitwise OR example

System.out.println(Integer.toBinaryString(two));
System.out.println(Integer.toBinaryString(four));
System.out.println(Integer.toBinaryString(result));

Output:
11111111111111111111111111111110
11111111111111111111111111111100
11111111111111111111111111111110

Đọc thêm: http://javarevisited.blogspot.com/2015/01/difference-b between-bitwsie-and-logical.html # ixzz45PCxdQhk


Không đúng khi các toán hạng là booleans và định dạng ngu ngốc.
Hầu tước Lorne

2
Điều này hữu ích cho tôi trong việc hiểu tại sao Long.valueOf (100 | 200) = 236. Đây là lý do: 0 1 1 0 0 1 0 0 | 1 1 0 0 1 0 0 0 = 1 1 1 0 1 1 0 0 = 128 64 32 0 8 4 0 0 = 236
donlys

1

Khi tôi có câu hỏi này, tôi đã tạo mã kiểm tra để có ý tưởng về điều này.

public class HelloWorld{

   public static boolean bool(){
      System.out.println("Bool");
      return true;
   }

   public static void main(String []args){

     boolean a = true;
     boolean b = false;

     if(a||bool())
     {
        System.out.println("If condition executed"); 
     }
     else{
         System.out.println("Else condition executed");
     }

 }
}

Trong trường hợp này, chúng tôi chỉ thay đổi giá trị bên trái của nếu điều kiện thêm a hoặc b.

|| Kịch bản, khi bên trái đúng [if (a || bool ())]

đầu ra "If condition executed"

|| Kịch bản, khi bên trái sai [if (b || bool ())]

Đầu ra-

Bool
If condition executed

Conclusion of || Khi sử dụng ||, bên phải chỉ kiểm tra khi bên trái là sai.

| Kịch bản, khi bên trái đúng [if (a | bool ())]

Đầu ra-

Bool
If condition executed

| Kịch bản, khi bên trái sai [if (b | bool ())]

Đầu ra-

Bool
If condition executed

Conclusion of | Khi sử dụng |, kiểm tra cả bên trái và bên phải.


0

| = bitwise hoặc, | | = logic hoặc


2
Thiếu điều đó | cũng là một toán tử boolean không ngắn mạch.
John Meagher

0

thông thường tôi sử dụng khi có toán tử gia tăng trước và tăng bài. Nhìn vào đoạn mã sau:

package ocjpPractice;
/**
 * @author tithik
 *
 */
public class Ex1 {

    public static void main(String[] args) {
    int i=10;
    int j=9;
    int x=10;
    int y=9;
    if(i==10 | ++i>j){
        System.out.println("it will print in first if");  
        System.out.println("i is: "+i);
    }

    if(x==10 ||++x>y){
        System.out.println("it will print in second if");   
        System.out.println("x is: "+x);
    }
    }
}

đầu ra:

nó sẽ in đầu tiên nếu
tôi là: 11

nó sẽ in thứ hai nếu
x là: 10

cả hai ifkhối đều giống nhau nhưng kết quả là khác nhau. khi có |, cả hai điều kiện sẽ được đánh giá. Nhưng nếu có ||, nó sẽ không đánh giá điều kiện thứ hai vì điều kiện thứ nhất đã đúng.


1
Tôi thấy điều này rất khó hiểu
NimChimpsky

0

Có nhiều trường hợp sử dụng cho thấy tại sao bạn nên đi ||thay vì |. Một số trường hợp sử dụng phải sử dụng |toán tử để kiểm tra tất cả các điều kiện.

Ví dụ: nếu bạn muốn kiểm tra xác thực mẫu và bạn muốn hiển thị cho người dùng tất cả các trường không hợp lệ bằng văn bản lỗi thay vì chỉ một trường không hợp lệ đầu tiên.

|| toán tử sẽ,

   if(checkIfEmpty(nameField) || checkIfEmpty(phoneField) || checkIfEmpty(emailField)) {
      // invalid form with one or more empty fields
   }

   private boolean checkIfEmpty(Widget field) {
      if(field.isEmpty()) {
        field.setErrorMessage("Should not be empty!");
        return true;
      }
      return false;
   }

Vì vậy, với đoạn mã trên, nếu người dùng gửi biểu mẫu với TẤT CẢ các trường trống, CHỈ nameFieldsẽ được hiển thị với thông báo lỗi. Nhưng, nếu bạn thay đổi nó thành,

   if(checkIfEmpty(nameField) | checkIfEmpty(phoneField) | checkIfEmpty(emailField)) {
      // invalid form with one or more empty fields
   }

Nó sẽ hiển thị thông báo lỗi thích hợp trên từng lĩnh vực không phân biệt trueđiều kiện.


0

Sau khi đọc kỹ chủ đề này vẫn chưa rõ ràng với tôi nếu sử dụng |như một toán tử logic có phù hợp với thực tiễn mẫu Java không.

Gần đây tôi đã sửa đổi mã trong một yêu cầu kéo giải quyết một bình luận trong đó

if(function1() | function2()){
  ...
}

phải đổi thành

boolean isChanged = function1();
isChanged |= function2();
if (isChanged){
  ...
}

Phiên bản thực tế được chấp nhận là gì?

Tài liệu Java không được đề cập đến |như là một toán tử OR không ngắn mạch logic.

Không quan tâm đến một cuộc bỏ phiếu nhưng nhiều hơn trong việc tìm ra tiêu chuẩn?! Cả hai phiên bản mã đang biên dịch và làm việc như mong đợi.





-2

| là một toán tử bitwise. | | là một toán tử logic.

Một sẽ lấy hai bit và hoặc chúng.

Người ta sẽ xác định sự thật (điều này HOẶC điều đó) Nếu điều này đúng hoặc đúng, thì câu trả lời là đúng.

Oh, và dang mọi người trả lời những câu hỏi này nhanh chóng.

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.