Operatori Logici e Operatori Relazionali in Java

Concetti Chiave
  • Operatori Relazionali: confrontano due valori e restituiscono un valore booleano che indica la relazione tra di essi.
  • Operatori Logici: operano su valori booleani e combinano risultati logici per produrre un nuovo valore booleano.
  • Corto Circuito: gli operatori && e || valutano il secondo operando solo se necessario, migliorando l'efficienza e prevenendo errori.

Operatori relazionali

Gli operatori relazionali determinano la relazione che un operando ha rispetto all'altro. In particolare, stabiliscono uguaglianza e ordinamento. Gli operatori relazionali sono mostrati di seguito:

Operatore Risultato
== Uguale a
!= Diverso da
> Maggiore di
< Minore di
>= Maggiore o uguale a
<= Minore o uguale a
Tabella 1: Operatori Relazionali in Java

L'esito di queste operazioni è un valore booleano. Gli operatori relazionali sono usati più di frequente nelle espressioni che controllano l'istruzione if e le varie istruzioni di ciclo.

Qualsiasi tipo in Java, inclusi interi, numeri a virgola mobile, caratteri e booleani, può essere confrontato utilizzando il test di uguaglianza == e il test di disuguaglianza !=. In Java l'uguaglianza è indicata con due segni di uguale, non con uno solo (un singolo segno di uguale è l'operatore di assegnazione). Soltanto i tipi numerici possono essere confrontati tramite gli operatori di ordinamento; cioè solo operandi interi, a virgola mobile e carattere possono essere messi a confronto per stabilire quale sia maggiore o minore.

Come indicato, il risultato prodotto da un operatore relazionale è un valore booleano. Per esempio, il seguente frammento di codice è perfettamente valido:

int a = 4;
int b = 1;
boolean c = a < b;

In questo caso il risultato di a<b (che è false) viene memorizzato in c.

Per chi proviene dal C/C++, occorre prestare attenzione a quanto segue. In C/C++ sono molto comuni istruzioni di questo tipo:

int completato;
// ...
if(!completato) ...   // Valido in C/C++
if(completato) ...    // ma non in Java.

In Java tali istruzioni devono essere scritte così:

if(completato == 0) ...  // Stile Java.
if(completato != 0) ...

Il motivo risiede nel fatto che Java non definisce true e false allo stesso modo del C/C++. In quest'ultimo, true è qualunque valore diverso da zero e false è zero. In Java, invece, true e false sono valori non numerici che non si riferiscono a zero o non-zero; di conseguenza, per verificare la condizione di zero o non-zero è necessario impiegare esplicitamente uno o più operatori relazionali.

Operatori logici booleani

Gli operatori logici booleani mostrati di seguito agiscono solo su operandi di tipo boolean. Tutti gli operatori binari combinano due valori booleani per produrre un valore booleano risultante.

Operatore Risultato
& AND logico
| OR logico
^ XOR logico (OR esclusivo)
|| OR a corto circuito
&& AND a corto circuito
! NOT logico unario
&= Assegnazione AND
|= Assegnazione OR
^= Assegnazione XOR
Tabella 2: Operatori Logici in Java
Operatore Risultato
== Uguale a
!= Diverso da
?: If-then-else ternario
Tabella 3: Operatori di Confronto in Java

L'operatore logico ! inverte lo stato booleano: !true == false e !false == true. La tabella seguente mostra l'effetto di ciascuna operazione logica:

A B A || B A && B A ^ B !A
Falso Falso Falso Falso Falso Vero
Vero Falso Vero Falso Vero Falso
Falso Vero Vero Falso Vero Vero
Vero Vero Vero Vero Falso Falso
Tabella 4: Risultato degli operatori Logici

Ecco un programma quasi identico all'esempio visto nella lezione sugli operatori bitwise, ma che opera su valori logici booleani invece che su bit binari:

// Dimostrare gli operatori logici booleani.
class LogicaBool {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        boolean c = a | b;
        boolean d = a & b;
        boolean e = a ^ b;
        boolean f = (!a & b) | (a & !b);
        boolean g = !a;

        System.out.println("        a = " + a);
        System.out.println("        b = " + b);
        System.out.println("      a|b = " + c);
        System.out.println("      a&b = " + d);
        System.out.println("      a^b = " + e);
        System.out.println("!a&b|a&!b = " + f);
        System.out.println("       !a = " + g);
    }
}

Dopo l'esecuzione si può osservare che le stesse regole logiche si applicano ai valori booleani così come ai bit. L'output mostra che la rappresentazione in forma di stringa di un valore booleano in Java è uno dei due letterali true oppure false:

        a = true
        b = false
      a|b = true
      a&b = false
      a^b = true
!a&b|a&!b = true
       !a = false

Corto Circuito degli operatori Logici

Java fornisce due operatori booleani particolarmente interessanti, non presenti in alcuni altri linguaggi. Si tratta delle versioni secondarie degli operatori AND e OR, comunemente noti come operatori logici short-circuit (a corto circuito). L'operatore || produce true quando A è true, indipendentemente dal valore di B. In modo analogo, l'operatore && produce false quando A è false, qualunque sia B. Usando le forme || e && invece delle forme | e &, Java evita di valutare l'operando destro quando il risultato dell'espressione può essere determinato dal solo operando sinistro. Ciò è particolarmente utile quando l'operando destro dipende dal valore di quello sinistro per funzionare correttamente. Per esempio, il frammento seguente sfrutta la valutazione a corto circuito per garantire che un'operazione di divisione sia valida prima di essere eseguita:

if (denominatore != 0 && numeratore / denominatore > 10)

Poiché viene impiegata la forma &&, non vi è rischio di eccezione a run-time se denominatore vale zero. Se la stessa riga fosse scritta usando la versione singola &, entrambi i lati verrebbero valutati, generando un'eccezione a run-time quando denominatore è zero.

Nella pratica è consuetudine usare le forme a corto circuito di AND e OR nelle situazioni che coinvolgono logica booleana, riservando le versioni a carattere singolo esclusivamente alle operazioni bit-wise. Vi sono tuttavia eccezioni a tale regola. Ad esempio:

if(c == 1 & e++ < 100) d = 100;

In questo caso l'uso di & assicura che l'operazione di incremento sia applicata a e indipendentemente dal fatto che c sia uguale a 1 o meno.

Consiglio

Terminologia ufficiale

La specifica formale di Java si riferisce agli operatori a corto circuito con i termini conditional-and e conditional-or.