Buono sconto 4% su Toner e Cartucce agli utenti AZpoint. SU Iomiricarico.it!!
|
Si ringrazia Claudio De Sio per la concessione del materiale pubblicato in questo articolo.
|
Operatori e flusso di controllo
Obiettivi:
Il Lettore al termine di questo capitolo dovrà essere in grado di
- Conoscere e saper utilizzare i vari operatori (unità 4.1).
- Conoscere e saper utilizzare i costrutti di programmazione semplici (unità
4.2, 4.3).
- Conoscere e saper utilizzare i costrutti di programmazione avanzati (unità
4.2, 4.4).
Unità didattica 4.1)
- Operatori di base
Di seguito è presentata una lista volutamente incompleta degli operatori che
Java ci mette a disposizione. Per alcuni di essi, l’utilizzo è alquanto raro.
- Operatore d’assegnazione:
=
- Operatori aritmetici :
somma
+
sottrazione
-
moltiplicazione
*
divisione
/
modulo
%
L’unico operatore che può risultare non familiare al lettore, è l’operatore
modulo. Il risultato dell’operazione modulo tra due numeri, coincide con il
resto della divisione fra essi. Per esempio
5%3=2
10%2=0
100%50=0
Dalla sintassi del linguaggio C, Java ha ereditato anche altri operatori
unari (con un solo operando) che, oltre che svolgere un’operazione, assegnano
anche il valore del risultato ad una variabile utilizzata nell’operazione:
somma e assegnazione
+=
sottrazione e assegnazione
-=
moltiplicazione e assegnazione
*=
divisione e assegnazione
/=
modulo e assegnazione
% =
In pratica se abbiamo:
int i=5;
scrivere:
i=i+2;
è equivalente a scrivere:
i+=2;
- Operatori di pre e post-incremento
incremento di un’unità
++
(pre e post)
decremento di un’unità
-- (pre e post)
Se vogliamo incrementare di una sola unità una variabile numerica, posso
equivalentemente scrivere:
i=i+1;
oppure:
i+=1;
ma anche:
i++;
oppure:
++i;
ottenendo comunque lo stesso risultato. Infatti, in tutti i casi, otterremo
che il valore della variabile i,
è stato incrementato di un’unità, ed assegnato nuovamente alla variabile
stessa. Quindi anche questi operatori svolgono due compiti (incremento ed
assegnazione). Parleremo di operatore di pre-incremento nel caso in cui
anteponiamo l’operatore d’incremento ++
alla variabile. Parleremo invece, di operatore di post-incremento nel caso in
cui posponiamo l’operatore di incremento alla variabile. La differenza tra
questi due operatori "composti", consiste essenzialmente nelle
priorità che essi hanno rispetto all’operatore di assegnazione. L’operatore
di pre-incremento, ha maggiore priorità dell’operatore di assegnazione =.
L’operatore di post-incremento, ha minor priorità rispetto all’operatore di
assegnazione =.
Il seguente esempio rende visibile la differenza tra i due operatori:
pre-incremento
x = 5;
y = ++x; si ha
x=6 e y=6
post-incremento
x = 5;
y = x++; si ha
x=6 e y=5
- Operatori bitwise:
NOT
~
AND
&
OR
|
XOR
^
shift a sinistra
<<
shift a destra
>>
shift a destra senza segno
>>>
AND e assegnazione
&=
OR e assegnazione
|=
XOR e assegnazione
^=
shift a sinistra e assegnazione
<<=
shift a destra e assegnazione
>>=
shift a destra con riempimento di zeri e assegnazione
>>>=
Tutti questi operatori binari, sono molto efficienti giacché agiscono direttamente
sui bit, ma in Java si utilizzano raramente. L’operatore NOT
~ è un cosiddetto operatore unario,
dato che si applica ad un solo operando.
Gli operatori AND &,
OR |,
e
XOR ^,
si applicano a coppie di operandi, e
svolgono le relative operazioni logiche di conversioni di bit riassunte nelle
seguente tabella:
|
Operando1 |
Operando2 |
Op1ANDOp2 |
Op1OROp2 |
Op1XOROp2 |
|
0 |
0 |
0 |
0 |
0 |
|
0 |
1 |
0 |
1 |
1 |
|
1 |
0 |
0 |
1 |
1 |
|
1 |
1 |
1 |
1 |
0 |
Gli operatori di shift, provocano lo scorrimento verso una direzione, dei bit
della rappresentazione binaria di un certo numero. Il numero dei bit da scorrere
è rappresentato dall’operando a destra dell’operazione. I bit che dopo lo
scorrimento si trovano al di fuori della rappresentazione binaria del numero,
vengono eliminati. I bit che invece "rimangono vuoti" vengono riempiti
con i valori 0
oppure 1
a seconda del caso. In particolare, lo scorrimento a sinistra provoca un
riempimento con i valori 0, per i bit lasciati vuoti sulla destra della
rappresentazione binaria del numero. Anche lo scorrimento a destra senza segno
riempie i bit lasciati vuoti con degli 0. Lo scorrimento a destra con segno
invece, provoca il riempimento di 0 oppure di 1, a seconda che l’ultima cifra
a sinistra prima dello scorrimento (bit del segno) sia 0 oppure 1, ovvero che la
cifra prima dello scorrimento sia positiva o negativa. Consideriamo i seguenti
esempi:
byte a=35; byte b=-8;
a = a>>2; b = b>>1;
rappresentazioni binarie
00100011 35 11111000 -8
>>2 >>1
00001000 8 11111100 -4
int a = -1;
a = a>>>24;
11111111111111111111111111111111 -1
>>>24
00000000000000000000000011111111 255
Possiamo notare che l’operazione di scorrimento a sinistra equivale, a
dividere l’operando di sinistra, per 2
elevato l’operando situato alla destra dell’operazione. Similmente, l’operazione
di scorrimento a destra equivale a moltiplicare l’operando di sinistra per 2
elevato l’operando situato sulla destra dell’operazione. Il risultato viene
arrotondato per difetto nelle operazioni con resto.
- Operatori relazionali o di confronto
Il risultato di queste operazioni è sempre un valore boolean,
ovvero true o
false.
uguale a
==
tutti i tipi
diverso da
!=
tutti i tipi
maggiore
>
solo i tipi numerici
minore
<
solo i tipi numerici
maggiore o uguale
>=
solo i tipi numerici
minore o uguale
<=
solo i tipi numerici
Notiamo che se confrontiamo due reference con l’operatore ==,
il risultato risulterà true
se e solo se i due reference
puntano allo stesso oggetto, false
altrimenti. Un classico errore che l’aspirante programmatore commette spesso,
è quello di scrivere =
in luogo di ==.
- Operatori logico - booleani
I seguenti sono operatori che utilizzano solo operandi di tipo booleano, ed
il risultato è di tipo boolean:
NOT logico
!
AND logico
&
OR logico
|
XOR logico
^
short circuit AND
&&
short circuit OR
||
AND e assegnazione
&=
OR e assegnazione
|=
XOR e assegnazione
^=
E’ consuetudine utilizzare le versioni short circuit di AND
ed OR.
Ad esempio, la seguente riga di codice, mostra come avvantaggiarsi della
valutazione logica di corto circuito per essere certi che il risultato di una
operazione di divisione sia valido prima di valutarlo:
boolean flag = (a!=0 && b/a>10)
Affinché l’espressione tra parentesi sia vera, bisogna che entrambi gli
operandi siano veri. Se il primo tra loro è in partenza falso, non ha senso
andare a controllare la situazione dell’altro operando. In questo caso
addirittura sarebbe dannoso essendoci il rischio di una divisione per zero.
Quest'operatore short – circuit, a differenza della sua versione tradizionale, fa
evitare il secondo controllo in caso di fallimento del primo.
Equivalentemente l'operatore short - circuit ||,
nel caso la prima espressione da testare risultasse verificata, convalida
l'intera espressione, senza nessun'altra (superflua) verifica.
- Concatenazione di stringhe con +
In Java l’operatore +, oltre che ad essere un operatore aritmetico, è
anche un operatore per concatenare stringhe. Per esempio il seguente frammento
di codice:
String nome = "James ";
String cognome = "Gosling";
String nomeCompleto = "Mr. " + nome + cognome;
farà in modo che la stringa nomeCompleto,
avrà come valore "Mr. James Gosling".
N.B.: se "sommiamo" un qualsiasi tipo di dato con una stringa, il
tipo di dato sarà automaticamente convertito in stringa, e ciò può risultare
molto utile.
- Priorità degli operatori
Nella seguente tabella sono riportati, in ordine di priorità, tutti gli
operatori di Java. Alcuni di essi non sono ancora stati trattati.
|
Separatori |
. [] () ; , |
|
da sx a dx |
++ -- + - ~ ! (tipi di dati) |
|
Da sx a dx |
* / % |
|
Da sx a dx |
+ - |
|
Da sx a dx |
<< >> >>> |
|
Da sx a dx |
< > <= >= instanceof |
|
Da sx a dx |
== != |
|
Da sx a dx |
& |
|
Da sx a dx |
^ |
|
Da sx a dx |
| |
|
Da sx a dx |
&& |
|
Da sx a dx |
|| |
|
Da dx a sx |
?: |
|
da dx a sx |
= *= /= %= += -= <<= >>=
>>>= &= ^= |= |
Il lettore non si spaventi! Non è necessario conoscere a memoria tutte le
priorità per programmare. Nell’incertezza, si possono sempre utilizzare le
parentesi tonde così come faremmo nell’aritmetica tradizionale.
|