Cosa significa type casting
Java è tipizzato staticamente: ogni valore ha un tipo, e il compilatore non ti permette di mescolare in silenzio tipi incompatibili. Il type casting è il modo in cui converti un valore da un tipo a un altro: a volte Java lo fa per te, altre volte devi chiederlo in modo esplicito.
Ci sono due direzioni. Passare da un tipo più piccolo a uno più grande (un int in un double) è sicuro e avviene automaticamente. Passare da un tipo più grande a uno più piccolo (un double in un int) può far perdere dati, quindi Java ti obbliga a scriverlo con un cast.
Allargamento: la conversione automatica
Una conversione di allargamento (widening) sposta un valore in un tipo con più spazio. Non si può perdere niente, quindi Java la fa per te senza cast:
L'int 7 entra in un double e diventa 7.0. L'ordine di allargamento dei numeri è byte -> short -> int -> long -> float -> double; assegnare un valore a un tipo che viene dopo in questa catena non richiede mai un cast. Ecco perché mescolare tipi nei calcoli spesso "funziona e basta": Java allarga prima l'operando più piccolo.
Restringimento: il cast esplicito
Andare nell'altra direzione, con una conversione di restringimento (narrowing), può far perdere dati, quindi il compilatore si rifiuta a meno che tu non metta il tipo di destinazione tra parentesi davanti al valore:
(int) pi è il cast. Nota cosa fa: tronca verso lo zero, eliminando semplicemente la parte decimale. 3.9 diventa 3 e -3.9 diventa -3. Non arrotonda. Se vuoi arrotondare, serve un altro strumento:
Dimenticare che un cast tronca è uno dei bug più comuni per chi inizia: se il tuo numero "arrotondato" è sempre più basso di uno, di solito il motivo è questo.
La trappola della divisione intera
Questa trappola prima o poi colpisce tutti. Quando entrambi gli operandi sono int, l'operatore / esegue una divisione intera e scarta il resto, prima che avvenga qualsiasi assegnazione a un double:
a / b è 7 / 2, calcolato interamente con aritmetica int, e dà 3. L'allargamento a double fatto dopo trasforma solo 3 in 3.0: il .5 è già perso. Fare prima il cast di un operando a double ((double) a / b) porta l'intera espressione in virgola mobile e dà il 3.5 che volevi. Basta convertire un solo lato; Java allarga l'altro per farli corrispondere.
Quando il restringimento va in overflow
Un cast non controlla se il valore ci sta. Se non ci sta, i bit vengono semplicemente tagliati e ottieni un risultato sorprendente, senza errori né avvisi:
300 non sta in un byte, quindi i bit alti vengono scartati e ottieni 44. È una perdita di dati "silenziosa": il programma funziona e dà una risposta sbagliata. Restringi solo quando sei sicuro che il valore stia nel tipo più piccolo.
Convertire tra numeri e stringhe
Una String è un oggetto, non un numero, quindi non puoi convertirla con (int): è un errore di compilazione. La conversione usa invece metodi dedicati:
Per passare dal testo a un numero si usano Integer.parseInt / Double.parseDouble. Se la stringa non è un numero valido (per esempio "hello"), questi metodi lanciano una NumberFormatException. Per passare da un numero al testo, usa String.valueOf(n) o concatena semplicemente con "", perché n + "" trasforma l'int in una String. Attento alla differenza tra "5" + 1 (che dà la stringa "51") e 5 + 1 (che dà 6): il + diventa concatenazione nel momento in cui entra in gioco una String.
Cast di oggetti
Il cast vale anche per i riferimenti a oggetti, non solo per i tipi primitivi. Puoi convertire un riferimento in un tipo collegato lungo una catena di ereditarietà: l'allargamento a un tipo padre è automatico, mentre il restringimento verso il basso richiede un cast esplicito ed è sicuro solo se l'oggetto è davvero di quel tipo:
Object o = "hello";
String s = (String) o; // OK: o si riferisce davvero a una String
Integer bad = (Integer) o; // compila, ma lancia ClassCastException a runtime
Il secondo cast compila, ma esplode a runtime con una ClassCastException perché l'oggetto è una String, non un Integer. Lo vedrai per bene quando arriverai all'ereditarietà e al polimorfismo; per ora ti basta sapere che la sintassi (Type) è la stessa idea applicata agli oggetti.
Domande frequenti
Cos'è il type casting in Java?
Il type casting è la conversione di un valore da un tipo di dato a un altro. Java fa automaticamente le piccole conversioni di "allargamento" (come da int a double), ma una conversione di "restringimento" che potrebbe perdere dati (come da double a int) richiede un cast esplicito: int n = (int) 3.9;.
Come si converte un double in int in Java?
Metti il tipo di destinazione tra parentesi prima del valore: int n = (int) 3.9;. Questo tronca verso lo zero (elimina la parte decimale), quindi ottieni 3, non 4. Per arrotondare, usa invece Math.round(3.9), che restituisce 4.
Come si converte una String in int in Java?
Una String non è un numero, quindi non puoi convertirla con (int). Usa Integer.parseInt("42") per ottenere un int, oppure Double.parseDouble("3.14") per un double. Se il testo non è un numero valido, questi metodi lanciano una NumberFormatException.