Effetto di un operatore bit per bit su un booleano in Java


118

Gli operatori bit per bit dovrebbero viaggiare sulle variabili e operare su di esse bit per bit. Nel caso di numeri interi, long, char questo ha senso. Queste variabili possono contenere l'intera gamma di valori imposti dalla loro dimensione.

Nel caso dei booleani, tuttavia, un booleano può contenere solo due valori. 1 = vero o 0 = falso. Ma la dimensione del booleano non è definita. Può essere grande quanto un byte o un po 'piccolo.

Allora qual è l'effetto dell'utilizzo di un operatore bit per bit su un booleano? La JVM lo traduce essenzialmente in un normale operatore logico e va avanti? Tratta il valore booleano come un'entità a bit singolo ai fini dell'operazione? O il risultato è indefinito insieme alla dimensione di un booleano?


1
Penso che non puoi usare un operatore bit per bit su un booleano. Solo sui numeri. Sono sicuro che ~ non funzionerà, non so cosa ne sarà degli altri operatori.
Martijn Courteaux

4
Puoi usarne alcuni, abbiamo appena scoperto un | utilizzato nel nostro codice precedente. Lo stiamo rimuovendo, ma questo codice è stato compilato e ha funzionato.
Daniel Bingham

9
Poiché uno è in cortocircuito e l'altro no (vedi la risposta di mobrule), prima di cambiare il | a || potresti voler assicurarti che le successive espressioni booleane non abbiano effetti collaterali che il programmatore originale intendeva eseguire sempre.
John M Gant

Risposte:


122

Gli operatori &, ^e |sono operatori bit per bit quando gli operandi sono tipi integrali primitivi. Sono operatori logici quando gli operandi sono booleani e in quest'ultimo caso viene specificato il loro comportamento. Vedere la sezione 15.22.2 delle specifiche del linguaggio Java per i dettagli.


57
In particolare, & e ^ e | sono gli operatori booleani logici non di cortocircuito.
Ken il

14
Ecco un collegamento diretto alla sezione menzionata sopra: docs.oracle.com/javase/specs/jls/se7/html/…
Andy Thomas,

Se quanto sopra è vero, perché ideone.com/oGSF7c lancia un'eccezione di puntatore nullo? Se l' |=operatore era logico, il programma non avrebbe mai dovuto eseguire la x.getValue()direttiva.
ikromm

1
@JohnKrommidas, la tua x è nulla, motivo per cui ricevi una NullPointerException. Devi istanziarlo.
Ben

4
@ Ben, come dice @Ken, la logica non è in cortocircuito, quindi viene valutata la seconda parte. Quindi a || x.foo()è sicuro se x è nullo, ma a | x.foo()non lo è. |=segue le stesse regole di |.
Michael Smith

86

L'utilizzo dell'operatore bit a bit può aggirare il comportamento di cortocircuito:

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

Se booleanExpression1()restituisce false,
booleanExpression2()non viene valutato nel primo caso e
booleanExpression2()(e qualsiasi effetto collaterale possa avere) viene valutato nel secondo caso,


2
E l'operazione bit per bit si esegue solitamente più velocemente di quella di cortocircuito (a condizione che la valutazione sia semplice)
rds

1
Il bit &per bit sarà più veloce, ma la chiamata alla seconda funzione potrebbe essere ignorata con l'uso di&&
NatNgs

20

Al di là di quanto trattato nelle altre risposte, vale la pena sottolinearlo &&e ||hanno una precedenza diversa da &e |.

Estratto dalla tabella delle precedenza (con la precedenza più alta in alto).

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

Cosa significa per te?

Assolutamente niente, a patto che ti attacchi solo &e |o solo &&e ||.

Ma, poiché |ha una precedenza maggiore di &&(al contrario di ||, che ha una precedenza inferiore), mescolarli liberamente potrebbe portare a comportamenti inaspettati.

Quindi a && b | c && dè lo stesso di a && (b | c) && d,
al contrario di quello a && b || c && dche sarebbe (a && b) || (c && d).

Per dimostrare che non sono la stessa cosa, considera un estratto dalla tabella della verità:

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

Se si desidera o avere la precedenza superiore E, si potrebbe utilizzare |e&& insieme, ma questo non è raccomandato.

Ma dovresti davvero metterle tra parentesi per chiarire la precedenza ogni volta che usi simboli diversi, cioè (a && b) || c(parentesi per chiarire la precedenza), a && b && c(non sono necessarie parentesi).


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.