Type Casting in Java
Converti tra tipi primitivi in Java con la conversione implicita widening e il cast esplicito narrowing, evitando gli errori più comuni.
Il type casting consiste nel convertire un valore da un tipo a un altro. In Java esistono due varianti: le conversioni widening, che avvengono automaticamente e non perdono informazioni, e le conversioni narrowing, che richiedono un cast esplicito e possono comportare perdita di dati.
Conversione widening (implicita)
Una conversione widening sposta un valore in un tipo più grande. Il compilatore la gestisce automaticamente — non è necessaria alcuna sintassi speciale:
int i = 100;
long l = i; // int → long (widening)
double d = l; // long → double (widening)
System.out.println(i); // 100
System.out.println(l); // 100
System.out.println(d); // 100.0L'ordine standard delle conversioni widening è:
byte → short → int → long → float → double
char ↗(char si allarga a int e oltre, ma non a short o byte.)
La conversione widening non perde mai il range — un long rientra sempre nel range di un double, anche se double non può rappresentare ogni valore long in modo esatto. Attenzione a questo gap di rappresentazione esatta con valori estremi.
Cast narrowing (esplicito)
Una conversione narrowing sposta un valore in un tipo più piccolo. Java rifiuta di farlo implicitamente perché i dati possono andare persi. È necessario indicarlo esplicitamente con (targetType):
double d = 9.99;
int i = (int) d; // explicit narrowing cast
System.out.println(i); // 9 — the fractional part is droppedIl cast tronca verso zero — non arrotonda.
Per i numeri interi, il cast mantiene solo i bit di ordine inferiore:
int big = 130;
byte b = (byte) big;
System.out.println(b); // -126 — overflow wraps aroundbyte è a 8 bit, con range -128…127. I bit di 130 (10000010) vengono interpretati come -126 in complemento a due.
Un cast comune: divisione intera in numero reale
L'aritmetica puramente intera usa la divisione intera — 5 / 2 == 2, non 2.5. Per ottenere un risultato reale, è necessario eseguire il cast di almeno un operando prima della divisione:
int total = 5;
int count = 2;
double avgWrong = total / count; // 2.0 — division is still integer
double avgRight = (double) total / count; // 2.5 — total widened firstQuesto è il motivo più comune per cui si ricorre a un cast.
Cast di riferimento
La sintassi (Type) funziona anche sugli oggetti — sebbene in quel caso si tratti di un controllo a runtime, non di una conversione. Eseguire il cast di un riferimento equivale a dire "fidatevi, questo oggetto è di tipo X":
Object o = "Hello";
String s = (String) o; // OK at runtime
System.out.println(s.length()); // 5
Object n = Integer.valueOf(7);
String bad = (String) n; // throws ClassCastException at runtimePer eseguire il cast di un riferimento in modo sicuro, è necessario verificare prima il tipo con instanceof:
Object o = "Hello";
if (o instanceof String) {
String s = (String) o; // guaranteed safe
System.out.println(s.length());
}Il pattern matching per instanceof (Java moderno) consente di effettuare il controllo e il cast in un unico passaggio. I cast di riferimento sono trattati in modo approfondito in OOP e Polimorfismo.
Un esempio funzionante
Quando il compilatore "aiuta" — e quando no
Un caso sottile a cui prestare attenzione: l'aritmetica su byte, short o char viene automaticamente promossa a int prima dell'operazione. Il risultato è un int:
byte a = 10;
byte b = 20;
// byte sum = a + b; // compile error: result is int
byte sum = (byte) (a + b); // explicit cast neededQuesto sorprende tutti la prima volta. Si può memorizzare il risultato in un int, oppure riconvertire con un cast.
Regole pratiche
- Widen liberamente — nessun cast necessario, nessuna perdita.
- Narrow con un cast e un controllo — assicurarsi che il valore rientri effettivamente nel tipo.
- Per la divisione in numeri reali tra interi, eseguire il cast di un operando a
double. - Per i calcoli monetari, non usare
double— usareBigDecimalper evitare errori di arrotondamento in virgola mobile binaria.
Cosa c'è dopo
Operatori Java — panoramica completa di tutti gli operatori disponibili nel linguaggio.