Dlaczego zwykle używamy || ponad | Jaka jest różnica?

219

Zastanawiam się tylko, dlaczego zwykle używamy logicznej OR ||między dwoma logicznymi OR |, a nie bitowymi OR , chociaż oba działają dobrze.

Mam na myśli, spójrz na następujące:

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

Czy możemy użyć |zamiast ||? To samo z &i &&.

Eng.Fouad
źródło
16
Większość ludzi zapomina o tym jest operatorem logicznym, który nie powoduje zwarcia, oprócz tego, że jest operatorem bitowym.
John Meagher,
1
Szczegóły dotyczące różnicy znajdują się w JLS. Zobacz java.sun.com/docs/books/jls/third_edition/html/…
John Meagher
64
One nie są takie same. Zapoznaj się z samouczkami na nich, szczególnie dotyczącymi oceny zwarcia w porównaniu z oceną chętną . ||i &&zwarcie podczas |i &są chętni.
Hovercraft Full Of Eels
4
Po prostu z ciekawości, w jakim przypadku rzeczywiście chciałbyś skorzystać z wersji bez zwarcia? Prawie zawsze widzę &&i ||, ale nigdy & |. Jeśli robisz coś, co zależy od efektów ubocznych, nie rozumiem, dlaczego używasz czegoś takiego, (a & b | c)ponieważ ktoś może łatwo pomyśleć „Mogę to zoptymalizować za pomocą zwartych wersji”.
Mike Bailey,
2
I oczywiście mają inny priorytet.
Hot Licks,

Odpowiedzi:

349

Jeśli użyjesz formularzy ||i &&, a nie formularzy |i &, Java nie będzie kłopotać się oceną samego operandu po prawej stronie.

Jest to kwestia tego, czy chcesz zewrzeć ocenę, czy nie - przez większość czasu.

Dobrym sposobem zilustrowania zalet zwarcia byłoby rozważenie następującego przykładu.

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

Kolejną korzyścią, jak wspomnieli Jeremy i Peter, w przypadku zwarcia jest zerowa kontrola odniesienia:

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

więcej informacji

Shawn
źródło
115
Kanonicznym przykładem jestfoo != null && foo.hasBar()
Jeremy
1
Jeśli dodasz około możliwego wyjątku odniesienia zerowego za pomocą | z komentarza @ Jeremy to świetna odpowiedź.
Peter Kelly
Pamiętaj również, że && i || oznacza instrukcję rozgałęzienia na poziomie kodu maszynowego (pamiętaj, że rozgałęzienia mogą powodować błędne przewidywania rozgałęzień), więc jeśli jesteś super pedantyczny co do wydajności, używaj ich tylko wtedy, gdy są one rzeczywiście wymagane ( foo != null && foo.hasBar()) lub szybsze ( b || foo.timeConsumingCall()). 99% programistów nie powinno jednak martwić się o ten poziom mikrooptymalizacji.
Jonathan Dickinson
3
Dziwię się, że nikt nie wspomniał, kiedy chcesz użyć |. Najczęstszym scenariuszem, w którym go używam, jest modyfikacja zmiennej podczas sprawdzania, np. (J> 3 | ++ i> 3) lub (++ i> 3 | modyfikujeGlobalAmongOtherThings () = true). Jednak niezbyt powszechne.
AndSoYouCode
8
Innym kanonicznym przykładem jest string == null || string.isEmpty();)
Peter Lawrey
83

| nie dokonuje oceny zwarcia w wyrażeniach boolowskich. ||przestanie oceniać, czy pierwszy operand jest prawdziwy, ale |nie zrobi tego.

Ponadto |można go użyć do wykonania operacji bitowej-LUB na wartościach bajt / short / int / long. ||Nie mogę.

Michael Myers
źródło
Podaj pełną odpowiedź, a ja ją zaakceptuję. Do tej pory jesteś pierwszym, który podniósł ten aspekt.
John Meagher,
Brakuje bitowego aspektu |
John Meagher
63

Tak więc, aby oprzeć się na innych odpowiedziach z przykładem, zwarcie jest kluczowe w następujących kontrolach obronnych:

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

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

Użycie |i &zamiast tego może spowodować NullPointerExceptionwyrzucenie tutaj.

Paul Bellora
źródło
Jeśli zastosujesz wzorzec NullObject, nie zrobiłby tego (a raczej zanegowałby odpowiedź). Powiedziałbym też, że sprawdzenie, czy foo jest niebieski, jest czymś wewnętrznym dla foo. Jeśli jest niebieski, to wykonaj coś nie powinno nic robić.
nicodemus13
@ nicodemus13 - dobre punkty, chociaż wzorzec Null Object jest tylko czasami pożądany, a ciało może być czymś innym niż innym wezwaniem do foo. „Kanoniczny przykład” Petera Lawreya jest najlepszy.
Paul Bellora,
@Khan: Tak, byłem raczej złośliwy, a Obiekt Null nie zawsze jest odpowiedni. Po prostu wolę przyzwyczaić się do podświadomego refaktoryzowania rzeczy. Nie ma nic szczególnie złego w twojej odpowiedzi.
nicodemus13
39

Logiczne ||i &&sprawdź prawą stronę tylko w razie potrzeby. |I &sprawdzić zarówno za każdym razem po bokach.

Na przykład:

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

Przepisz to:

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

Inny przykład:

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

Przepisz to:

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
...
Dair
źródło
18

Zwróć też uwagę na częstą pułapkę: operatorzy nie leniwi mają pierwszeństwo przed operatorami leniwymi, więc:

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

Zachowaj ostrożność podczas ich mieszania.

Pan Smith
źródło
15

Oprócz zwarć należy również pamiętać, że wykonywanie operacji logiki bitowej na wartościach innych niż 0 lub 1 ma zupełnie inne znaczenie niż logika warunkowa. Chociaż zwykle jest to samo dla |i ||, z &i &&otrzymujesz bardzo różne wyniki (np. 2 & 4Jest 0 / fałsz, podczas gdy 2 && 4jest 1 / prawda).

Jeśli rzecz, którą otrzymujesz z funkcji, jest w rzeczywistości kodem błędu i testujesz na wartość inną niż 0, może to mieć duże znaczenie.

Nie jest to tak duży problem w Javie, w której musisz jawnie pisać na klawiaturze, aby wstawić wartość logiczną lub porównać z 0 lub podobnymi, ale w innych językach o podobnej składni (C / C ++ i in.) Może być dość mylący.

Zauważ też, że & i | może mieć zastosowanie tylko do wartości typu całkowitoliczbowego, a nie do wszystkiego, co może być równoważne testowi boolowskiemu. Ponownie, w językach innych niż Java, istnieje wiele rzeczy, które mogą być użyte jako logiczne z niejawnym != 0porównaniem (wskaźniki, zmiennoprzecinkowe, obiekty z operator bool()itd.), A operatory bitowe są prawie zawsze nonsensowne w tych kontekstach.

puszysty
źródło
3
Cieszę się, że przynajmniej ktoś wspomniał o całym celu istnienia operatorów bitowych.
ulidtko
9

Jedyny raz, którego użyjesz |lub &zamiast ||lub&& jest, gdy masz bardzo proste wyrażenia boolowskie, a koszt skrótu (tj. Oddziału) jest większy niż czas, który oszczędzasz, nie oceniając późniejszych wyrażeń.

Jest to jednak mikrooptymalizacja, która rzadko ma znaczenie, z wyjątkiem kodu o najwyższym poziomie.

Peter Lawrey
źródło
1
Byłoby interesujące, czy kompilator robi to automatycznie w niektórych przypadkach.
starblue
Być może JIT mógłby, ale kompilator zwykle zajmuje się jedynie prostymi optymalizacjami.
Peter Lawrey,
2
Tak, widziałem również sytuacje, w których | jest znacznie szybszy niż obciążenie gałęzi ||, szczególnie na procesorach bez prognozy rozgałęzienia lub z ograniczoną prognozą. To rzadkie, ale nie niespotykane. Jeden z moich współpracowników wdał się w wojnę o wycofanie w pewnym kodzie z kontrahentem, ponieważ (prawidłowo) używał | a wykonawca nadal myślał, że to „źle”.
puszysty
4
@Fluffy, morał tej historii jest taki, że jeśli zrobisz coś trudnego, musisz skomentować, dlaczego to zrobiłeś, lub twoje wysiłki mogą zostać zmarnowane później. ;)
Peter Lawrey,
1
Tak, w końcu dodał komentarz (według mojej sugestii, jak zmusić wykonawcę, aby przestał go „naprawiać”) i wszystko jest w porządku.
puszysty
8

|| jest logicznym lub operatorem, podczas gdy | jest bitową lub operatorem.

boolean a = true;
boolean b = false;

if (a || b) {
}

int a = 0x0001;
a = a | 0x0002;
Jorge Ferreira
źródło
1
Brak tego | jest również zwartym operatorem logicznym.
John Meagher
2
@John Meagher: Jest to domniemane, ponieważ jest bitowe .
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
@ L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ jak zmieniłeś swoje imię i styl w swoim profilu?
UdayKiran Pulipati
8

a | b: w każdym przypadku oceń b

a || b: ocenia b tylko wtedy, gdy a ocenia na fałsz

użytkownik18596
źródło
7

Oprócz tego, że | jest operatorem bitowym: || jest operatorem zwarcia - gdy jeden element jest fałszywy, nie sprawdzi pozostałych.

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

jeśli coś jest PRAWDA, || nie oceni niczego, podczas gdy | zrobi. Jeśli zmienne w instrukcjach if są faktycznie wywołaniami funkcji, użyj || prawdopodobnie oszczędza dużo wydajności.

Michael Stum
źródło
Dlaczego miałbyś kiedykolwiek używać | w instrukcji if. || ma wartość logiczną, | nie jest, | byłby logiczny tylko wtedy, gdy już pracujesz na dwóch wartościach logicznych.
FlySwat
To pierwsza odpowiedź na wszystko.
John Meagher,
Ta odpowiedź jest niepoprawna. Jeśli coś jest NIEAKTYWNE, obaj operatorzy przejdą do następnego operandu. Różnica powstaje tylko wtedy, gdy pierwszy operand jest prawdziwy.
Michael Myers
Szkoda, że ​​ma absolutnie absurdalny przykład.
FlySwat
Nie mam pojęcia, dlaczego ktokolwiek miałby używać lub & w instrukcji if dla prostego porównania boolowskiego, ale jest to całkowicie legalne, i faktycznie widziałem przykłady tego, kiedy zacząłem uczyć się programowania.
Michael Stum
3
| is the binary or operator

|| is the logic or operator
Lucas S.
źródło
2
Brak tego | jest również zwartym operatorem logicznym.
John Meagher,
3

Operatorzy ||i &&nazywane są operatory warunkowe , natomiast |i &są nazywane bitowe operatorów . Służą do różnych celów.

Operatory warunkowe działają tylko z wyrażeniami, które statycznie oceniają booleanna lewą i prawą stronę.

Operatory bitowe działają z dowolnymi operandami numerycznymi.

Jeśli chcesz wykonać logiczne porównanie, powinieneś użyć operatorów warunkowych , ponieważ dodasz do kodu pewien rodzaj bezpieczeństwa typu.

Bruno Reis
źródło
Um, |a &także są operatorami warunkowymi. Zobacz link w moim komentarzu do oryginalnego postu.
Hovercraft Full Of Eels,
@Hovercraft Full Of Eels: Ten wykres jest nieco mylący; odnosi się do nich jako operatorów warunkowych TYLKO w kontekście wartości logicznych, gdzie są matematycznie równoważne z chętnymi operatorami logicznymi. Kiedy zaczynasz zajmować się rzeczami, które mają wartości inne niż 0 lub 1, wartości zmiennoprzecinkowe, wskaźniki lub cokolwiek innego, porównanie się załamuje.
puszysty
@fluffy: wykres nie zawiera niczego mylącego, ponieważ dyskusja dotyczyła tylko operatorów logicznych. To, że |i &mogą być używane jako operatory bitowe, jest zupełnie odrębną kwestią.
Hovercraft Full Of Eels
1
Bardziej trafne byłoby nazywanie ich operatorami bitowymi wykorzystującymi wartości boolowskie, a nie operatorami logicznymi. Po prostu DZIAŁAJĄ, aby być matematycznie równoważnymi, gdy jest tylko jeden bit.
puszysty
2

Uwaga dodatkowa: Java ma | = ale nie || =

Przykład, kiedy musisz użyć || ma miejsce, gdy pierwsze wyrażenie jest testem sprawdzającym, czy drugie wyrażenie wybuchłoby. np. za pomocą jednego | w poniższym przypadku może powstać NPE.

public static boolean isNotSet(String text) {
   return text == null || text.length() == 0;
}
Peter Lawrey
źródło
2

Inne odpowiedzi wykonały dobrą robotę, pokrywając różnicę funkcjonalną między operatorami, ale odpowiedzi mogą dotyczyć niemal każdego istniejącego obecnie języka C. Pytanie jest oznaczone tagiem, więc postaram się odpowiedzieć konkretnie i technicznie na język Java.

&i |mogą być albo całkowitymi bitowymi operatorami, albo logicznymi operatorami logicznymi. Składnia dla operatorów bitowych i logicznych ( §15.22 ) jest następująca:

AndExpression:
  EqualityExpression 
  AndExpression & EqualityExpression

ExclusiveOrExpression:
  AndExpression 
  ExclusiveOrExpression ^ AndExpression

InclusiveOrExpression:
  ExclusiveOrExpression 
  InclusiveOrExpression | ExclusiveOrExpression

Składnia EqualityExpressionjest zdefiniowana w § 15.21 , który wymaga RelationalExpressionzdefiniowania w § 15.20 , który z kolei wymaga ShiftExpressioni ReferenceTypezdefiniowany odpowiednio w §15.19 i §4.3 . ShiftExpressionwymaga AdditiveExpressionzdefiniowanego w § 15.18 , który kontynuuje drążenie w dół, definiując podstawowe arytmetyki, operatory jednoargumentowe itp. drążyReferenceType wszystkie różne sposoby reprezentowania typu. (Chociaż ReferenceTypenie obejmuje typów pierwotnych, ostatecznie jest wymagana definicja typów pierwotnych, ponieważ mogą one być typem wymiaru tablicy, którym jest a ReferenceType.)

Operatory bitowe i logiczne mają następujące właściwości:

  • Operatory te mają różny priorytet, przy &czym mają najwyższy i |najniższy priorytet.
  • Każdy z tych operatorów jest składniowo lewostronny (każda grupa od lewej do prawej).
  • Każdy operator jest przemienny, jeśli wyrażenia operandu nie mają skutków ubocznych.
  • Każdy operator jest skojarzony.
  • Operatory bitowe i logiczne mogą być użyte do porównania dwóch operandów typu numerycznego lub dwóch operandów typu boolean. Wszystkie pozostałe przypadki powodują błąd czasu kompilacji.

Rozróżnienie, czy operator służy jako operator bitowe lub operator logiczny zależy od tego, czy są to argumenty „przekształcić w pierwotnej integralną typu” ( §4.2 ), czy są one typu booleanlub Boolean( §5.1.8 ).

Jeśli operandy są typami integralnymi, promocja binarna numeryczna ( § 5.6.2 ) jest wykonywana na obu operandach, pozostawiając je jako longs lub ints dla operacji. Typ operacji będzie typem (promowanych) operandów. W tym momencie &będzie bitowe ORAZ, ^będzie bitowo wykluczające LUB, i |będzie bitowo włącznie LUB. ( §15.22.1 )

Jeśli operandy są booleanlub Boolean, operandy zostaną poddane konwersji rozpakowywania, jeśli to konieczne ( §5.1.8 ), a typem operacji będzie boolean. &spowoduje, truejeśli oba operandy są true, ^spowoduje, trueże oba operandy będą różne, i |spowoduje, trueże którykolwiek z nich jest true. ( §15.22.2 )

Natomiast && jest „operatorem warunkowym” ( § 15.23 ) i ||„operatorem warunkowym” ( §15.24 ). Ich składnia jest zdefiniowana jako:

ConditionalAndExpression:
  InclusiveOrExpression 
  ConditionalAndExpression && InclusiveOrExpression

ConditionalOrExpression:
  ConditionalAndExpression 
  ConditionalOrExpression || ConditionalAndExpression

&&jest podobny &, z tym wyjątkiem, że ocenia prawy operand tylko wtedy, gdy lewy jest true. ||jest podobny |, z tym wyjątkiem, że ocenia prawy operand tylko wtedy, gdy lewy jest false.

Warunkowe-I ma następujące właściwości:

  • Operator warunkowy i jest składniowo lewostronnie asocjatywny (grupuje od lewej do prawej).
  • Operator warunkowy i operator jest w pełni asocjatywny zarówno pod względem skutków ubocznych, jak i wartości wyniku. To znaczy dla wszystkich wyrażeń a, ba cocena wyrażenia ((a) && (b)) && (c)daje ten sam wynik, z tymi samymi skutkami ubocznymi występującymi w tej samej kolejności, co ocena wyrażenia (a) && ((b) && (c)).
  • Każdy operand operatora warunkowego i operatora musi być typu booleanlub Boolean, inaczej wystąpi błąd czasu kompilacji.
  • Typ wyrażenia warunkowego i jest zawsze boolean.
  • W czasie wykonywania najpierw oceniane jest wyrażenie po lewej stronie argumentu; jeśli wynik ma typ Boolean, jest poddawany konwersji rozpakowywania ( §5.1.8 ).
  • Jeśli wartością wynikową jest false, wartość wyrażenia warunkowego i wyrażenia jest, falsea wyrażenie operandu po prawej stronie nie jest oceniane.
  • Jeśli wartość lewego operandu wynosi true, wówczas ocenia się prawe wyrażenie; jeśli wynik ma typ Boolean, jest poddawany konwersji rozpakowywania ( §5.1.8 ). Wynikowa wartość staje się wartością wyrażenia warunkowego i wyrażenia.
  • W ten sposób &&oblicza ten sam wynik, co &na booleanoperandach. Różni się tylko tym, że wyrażenie operandu po prawej stronie jest oceniane warunkowo, a nie zawsze.

Warunkowe-Lub ma następujące właściwości:

  • Operator warunkowy lub jest składniowo lewostronnie asocjatywny (grupuje od lewej do prawej).
  • Operator warunkowy lub operator jest w pełni asocjatywny zarówno pod względem skutków ubocznych, jak i wartości wyniku. To znaczy, dla wszystkich wyrażeń a, bi cocena wyrażenia ((a) || (b)) || (c)daje ten sam wynik, z tymi samymi skutkami ubocznymi występującymi w tej samej kolejności, co ocena wyrażenia (a) || ((b) || (c)).
  • Każdy operand operatora warunkowego lub operator musi być typu booleanlub Boolean, inaczej wystąpi błąd kompilacji.
  • Typem wyrażenia warunkowego lub jest zawsze boolean.
  • W czasie wykonywania najpierw oceniane jest wyrażenie po lewej stronie argumentu; jeśli wynik ma typ Boolean, jest poddawany konwersji rozpakowywania ( §5.1.8 ).
  • Jeśli wartością wynikową jest true, wartość wyrażenia warunkowego lub wyrażenia jest, truea wyrażenie operandu po prawej stronie nie jest oceniane.
  • Jeśli wartość lewego operandu wynosi false, wówczas ocenia się prawe wyrażenie; jeśli wynik ma typ Boolean, jest poddawany konwersji rozpakowywania ( §5.1.8 ). Wynikowa wartość staje się wartością warunkowego lub wyrażenia.
  • W ten sposób ||oblicza ten sam wynik, co |on booleanlub Booleanoperandy. Różni się tylko tym, że wyrażenie operandu po prawej stronie jest oceniane warunkowo, a nie zawsze.

W skrócie, jak @JohnMeagher wielokrotnie zwracał uwagę w komentarzach, &i |są w rzeczywistości, bez zwierania operatorów logicznych w przypadku konkretnego z argumentów będących albo booleanalbo Boolean. Przy dobrych praktykach (tj. Bez efektów wtórnych) jest to niewielka różnica. Gdy argumenty nie są booleanS lub Booleans, jednak operatorzy zachowują się bardzo różnie: bitowe i operacje logiczne po prostu nie porównać również na wysokim poziomie programowania Java.

Brian S.
źródło
2

1). (Wyrażenie1 | wyrażenie2), | operator oceni wyrażenie2 niezależnie od tego, czy wynik wyrażenia 1 jest prawdziwy, czy fałszywy.

Przykład:

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). (Wyrażenie 1 || wyrażenie 2), || operator nie oceni wyrażenia2, jeśli wyrażenie1 jest prawdziwe.

Przykład:

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;
    }
}
Veeresh
źródło
1

|| zwraca wartość logiczną poprzez OR'ing dwóch wartości (dlatego jest znany jako LOGICAL lub)

TO ZNACZY:

if (A || B) 

Zwróciłby wartość true, jeśli A lub B jest true, lub false, jeśli oba są false.

| jest operatorem, który wykonuje bitową operację na dwóch wartościach. Aby lepiej zrozumieć operacje bitowe, możesz przeczytać tutaj:

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

FlySwat
źródło
1

Jedną z głównych różnic jest to, że || i && wykazują „zwarcie”, więc RHS będzie oceniany tylko w razie potrzeby.

Na przykład

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

Powyżej, jeśli a jest prawdą, to b nie będzie testowane, a ścieżka1 zostanie wykonana. Jeśli | został użyty, wówczas obie strony zostałyby ocenione, nawet jeśli „a” jest prawdziwe.

Zobacz tutaj i tutaj , aby uzyskać więcej informacji.

Mam nadzieję że to pomoże.

Alex H.
źródło
1

Przydatny może być brak zwarcia. Czasami chcesz się upewnić, że dwa wyrażenia oceniają. Załóżmy na przykład, że masz metodę, która usuwa obiekt z dwóch oddzielnych list. Możesz zrobić coś takiego:

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));
    }
}

Jeśli zamiast tego twoja metoda użyłaby argumentu warunkowego, nie powiodłoby się usunięcie obiektu z drugiej listy, jeśli pierwsza lista zwróciłaby wartość false.

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

Nie jest to niezwykle przydatne i (jak w przypadku większości zadań programistycznych) można to osiągnąć innymi środkami. Ale jest to przypadek użycia bitandów.

ktbiz
źródło
1

Podstawowa różnica między nimi polega na tym, że | najpierw konwertuje wartości na binarne, a następnie wykonuje operację bitową. Tymczasem || nie konwertuje danych na dane binarne i po prostu wykonuje wyrażenie lub wyrażenie w oryginalnym stanie.

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

Czytaj więcej: http://javarevisited.blogspot.com/2015/01/difference-between-bitwsie-and-logical.html#ixzz45PCxdQhk

Avinash Nath
źródło
Nieprawdziwe, kiedy operandy to booleany i głupie formatowanie.
Markiz Lorne
2
Pomogło mi to zrozumieć, dlaczego Long.valueOf (100 | 200) = 236. Oto dlaczego: 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 18.12.2016
1

Kiedy miałem to pytanie, stworzyłem kod testowy, aby dowiedzieć się o tym.

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");
     }

 }
}

W tym przypadku zmieniamy tylko wartość po lewej stronie, jeśli warunek dodaje a lub b.

|| Scenariusz, gdy lewa strona jest prawdziwa [if (a || bool ())]

wynik "If condition executed"

|| Scenariusz, gdy lewa strona jest fałszywa [if (b || bool ())]

Wynik-

Bool
If condition executed

Conclusion of || Podczas używania ||prawa strona sprawdza tylko, gdy lewa strona jest fałszywa.

| Scenariusz, gdy prawda po lewej stronie [if (a | bool ())]

Wynik-

Bool
If condition executed

| Scenariusz, w którym wartość false po lewej stronie [if (b | bool ())]

Wynik-

Bool
If condition executed

Conclusion of | Podczas używania |sprawdź zarówno lewą, jak i prawą stronę.

JustCode
źródło
0

| = bitowe lub, || = logika lub

MagicKat
źródło
2
Brak tego | jest również zwartym operatorem logicznym.
John Meagher,
0

zwykle używam, gdy jest operator wstępnego i końcowego. Spójrz na następujący kod:

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);
    }
    }
}

wynik:

wydrukuje się pierwszy, jeśli
i wynosi: 11

wydrukuje się drugi, jeśli
x wynosi: 10

oba ifbloki są takie same, ale wynik jest inny. gdy będzie |, oba warunki zostaną ocenione. Ale jeśli tak ||, nie oceni drugiego warunku, ponieważ pierwszy warunek jest już spełniony.

Tithi
źródło
1
Uważam to za bardzo mylące
NimChimpsky
0

Istnieje wiele przypadków użycia sugerujące, dlaczego należy udać się do ||zamiast |. Niektóre przypadki użycia muszą korzystać |z operatorem, aby sprawdzić wszystkie warunki.

Na przykład, jeśli chcesz sprawdzić sprawdzanie poprawności formularza i chcesz pokazać użytkownikowi wszystkie nieprawidłowe pola z tekstami błędów, a nie tylko pierwsze nieprawidłowe pole.

|| operator byłby

   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;
   }

Tak więc przy powyższym fragmencie, jeśli użytkownik prześle formularz ze WSZYSTKIMI pustymi polami, TYLKO nameFieldzostanie wyświetlony komunikat o błędzie. Ale jeśli zmienisz to na,

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

Wyświetli odpowiedni komunikat o błędzie na każdym polu, niezależnie od truewarunków.

Bharath Mg
źródło
0

Po uważnym przeczytaniu tego tematu wciąż nie jest dla mnie jasne, czy używanie go |jako operatora logicznego jest zgodne z praktykami wzorcowymi Java.

Niedawno zmodyfikowałem kod w żądaniu ściągnięcia adresując komentarz gdzie

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

musiał zostać zmieniony na

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

Jaka jest faktycznie zaakceptowana wersja?

Dokumentacja Java nie jest wspominana |jako logiczny operator OR, który nie powoduje zwarcia.

Nie interesuje Cię głosowanie, a bardziej znalezienie standardu ?! Obie wersje kodu kompilują się i działają zgodnie z oczekiwaniami.

Dan M.
źródło
-1

|| jest logiczne lub i jest nieco mądry lub.

Steve Moyer
źródło
-2

| jest operatorem bitowym. || jest operatorem logicznym.

Jeden bierze dwa bity i / lub je.

Ustalimy prawdę (to LUB to) Jeśli to prawda lub prawda, to odpowiedź jest prawdą.

Och, i niech ludzie szybko odpowiedzą na te pytania.

scubabbl
źródło