Po pierwsze, pewne tło: jestem nauczycielem informatyki i staram się wprowadzić operatorów logicznych języka java do mojej klasy 10. Mój nauczyciel-mentor przejrzał przygotowany przeze mnie arkusz roboczy i skomentował, że mogę pozwolić im użyć tylko jednego & lub | oznaczać operatorów, ponieważ „robią to samo”.
Zdaję sobie sprawę z różnicy między & i &&.
& jest operatorem bitowym przeznaczonym do stosowania między liczbami całkowitymi, do wykonywania „kruszenia bitów”.
&& to operator warunkowy przeznaczony do użycia między wartościami logicznymi.
Aby udowodnić, że operatorzy ci nie zawsze „robią to samo”, postanowiłem znaleźć przykład, w którym użycie bitowej między wartościami logicznymi doprowadziłoby do błędu. Znalazłem ten przykład
boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10;
conditional = (i<j) || (i=3) > 5 ; // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10;
bitwise = (i>j) & (i=3) > 5; // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10;
conditional = (i>j) && (i=3) > 5; // value of i after oper: 10
System.out.println(conditional+ " "+ i);
Ten przykład pokazuje, że jeśli wartość musi zostać zmieniona przez drugą połowę wyrażenia, doprowadziłoby to do różnicy między wynikami, ponieważ bitowy jest chętnym operatorem, podczas gdy warunek zachowuje się jak zwarcie (nie ocenia drugiej połowa, jeśli pierwsza połowa jest fałszywa w przypadku && i prawdziwa w przypadku ||).
Mam problem z tym przykładem. Dlaczego chcesz zmienić wartość w tym samym czasie, gdy porównujesz ją? Nie wydaje się to dobrym sposobem na kodowanie. Zawsze byłem niechętny wykonywaniu wielu operacji w jednym wierszu w moim kodzie produkcyjnym. Wygląda na to, że zrobiłby to „kodujący kowboj” bez sumienia co do możliwości utrzymania jego kodu. Wiem, że w niektórych domenach kod musi być tak zwarty, jak to możliwe, ale z pewnością jest to ogólnie słaba praktyka?
Mogę wyjaśnić mój wybór zachęcania do korzystania z && i || ponad i | ponieważ jest to przyjęta konwencja kodowania w inżynierii oprogramowania .
Ale czy ktoś mógłby mi podać lepszy, nawet rzeczywisty przykład użycia operatora bitowego w wyrażeniu warunkowym?
źródło
bitwise = !(true & true == false);
icondition = !(true && true == false);
będzie oceniać zarówno na true, a więc w tym przypadku są one wymienne? Być może składniowo, ponieważ kod nadal się kompiluje. Zgodziłbym się, że są one używane semantycznie do różnych rzeczy, jak wspomniałem w ust. 2. Mówicie to! i „prawie nigdy nie pojawiają się w stanie warunkowym”. Szukam tych „prawie nigdy” przypadków i zastanawiam się, czy istnieją one zgodnie z prawem.Operatory niebędące bitami
&&
i||
są operatorami zwarć. Innymi słowy,&&
jeśli, jeśli LHS jest fałszywe, RHS nigdy nie będzie oceniane; ze||
jeśli LHS jest prawdą, wówczas RHS nigdy nie będą oceniane. Z drugiej strony operatory bitowe&
i|
nie powodują zwarcia i zawsze będą oceniać zarówno LHS, jak i RHS. W przeciwnym razie są równoważne wif
instrukcji.Jedyną rzeczą, w której widzę wartość w stosowaniu operatorów bez zwarć, jest to, czy RHS ma jakiś pożądany efekt uboczny, który chcesz zdarzyć we wszystkich przypadkach. Nie mogę wymyślić konkretnego przykładu, w którym chciałbyś tego i nie sądzę, że to dobra praktyka, ale taka jest różnica.
źródło
Ogólna filozoficzna odpowiedź brzmi: użycie operatorów bitowych dla operatorów logicznych jest nietypowe i sprawia, że kod jest trudniejszy do odczytania. W praktyce (w przypadku kodu, który jest produkowany), bardziej czytelny kod jest łatwiejszy w utrzymaniu, a zatem bardziej pożądany.
W przypadku rzeczywistego wykorzystania potrzeby operatorów zwarć zobacz przypadki takie jak:
Tego typu operacje często pojawiają się w kodzie rzeczywistym.
źródło
&
jest „trudniejszy do odczytania” niż 2? Nie mam przykładu, w którym 2 operatory nie działają w taki sam sposób dla operandów boolowskich. Zgadzam się z twoją opinią na temat bardziej czytelnego i łatwiejszego do utrzymania kodu. Chcę ich zachęcić do napisania pięknego kodu. Ale posiadanie jakiegoś dowodu w mojej torbie narzędzi byłoby bardziej przekonujące niż „ponieważ tak powiedziałem”. Podaję to jako standard pod tym linkiem i być może będę musiał polegać na tym samym, jeśli nie otrzymam przykładu, którego szukam. Jak zapytałem @Steve Haigh: czy Java powinna wskazywać to jako niewłaściwe użycie?Użyjesz operatorów bitowych, jeśli porównasz wyliczenia maski bitowej. Na przykład masz wyliczenie stanów i obiekt, który może znajdować się w więcej niż jednym z tych stanów. W takim przypadku zrobisz bitowo lub przypiszesz więcej niż jeden stan do swojego obiektu.
na przykład
state = CONNECTED | IN_PROGRESS
gdzieCONNECTED could be 0x00000001
iIN_PROGRESS 0x00000010
Aby uzyskać więcej informacji, zapoznaj się z dokumentacją wyliczania flagi.
źródło
prostszy przykład zła:
tutaj masz dwa warunki, oba są niezerowe; ale bitowa
&
powoduje zero.źródło
(condA && condB)
błędy, ponieważ && nie działa przez 2int
s, tylko 2 booleany.(condA & condB)
podczas gdy poprawne, ocenia naint
iw java nie możemy powiedzieć,if(int)
więc również błędy. Ale jako pierwszy rozumiesz, czego szukam - dokładnie ten przykład zła .(Boolean(condA) && Boolean(condB))
(myślę, żeBoolean(x)
totrue
dla liczb całkowitych niezerowych, prawda?)((condA!=0) && (condB!=0))
?if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }
wykonanie obu instrukcji print.