Il meccanismo di casting in Java (type casting) consente al programmatore di convertire esplicitamente o implicitamente un valore di un tipo in un altro. Storicamente, questa funzionalità è ereditata da C e C++, ma in Java è limitata per aumentare la type safety e prevenire bug nascosti legati a overflow o perdita di dati.
Problema consiste nella possibilità di un ClassCastException quando si effettuano cast di tipi di riferimento, oltre alla perdita di precisione quando si castano tipi primitivi, ad esempio, nel passaggio da double a int. Possono verificarsi errori logici durante il cosiddetto "downcasting" (casting verso un sottotipo), se l'istanza non appartiene a quella classe.
Soluzione consiste in una rigorosa separazione:
Esempio di codice per primitivi:
int i = 100; long l = i; // casting implicito (int -> long) double d = l; // implicito (long -> double) int i2 = (int) d; // casting esplicito (perdita della parte frazionaria)
Esempio di codice per tipi di riferimento:
Object obj = "Hello"; // upcasting, implicito String s = (String) obj; // downcasting, esplicito
Caratteristiche chiave:
Può il compilatore Java prevenire qualsiasi errore di casting?
Risposta: No, il compilatore cattura solo errori evidenti in fase di compilazione. Se il casting è possibile nella struttura dei tipi (ad esempio, Object -> String), ma la variabile contiene effettivamente un oggetto di un tipo incompatibile, l'errore si manifesterà solo durante l'esecuzione con ClassCastException.
Integer eredita da Long, e posso scrivere Integer i = (Integer) someLong?
Risposta: No, Integer e Long sono classi wrapper indipendenti e non possono essere downcastate tra loro. Entrambi ereditano da Number, ma non l'uno dall'altro. Il casting del tipo (Integer) (Object) 1L; causerà ClassCastException.
Nel casting esplicito da float a int avviene l'arrotondamento della parte frazionaria?
Risposta: No, viene troncata la parte frazionaria senza arrotondamento:
float f = 3.99f; int i = (int) f; // i == 3, non 4
Un sviluppatore riceve una collezione di Object, cast ogni elemento al proprio tipo, ma non controlla instanceof. Il progetto crolla costantemente con ClassCastException durante dati non validi.
Pro:
Contro:
Tutte le operazioni di downcasting vengono eseguite all'interno di if (obj instanceof TargetType) con gestione esplicita degli errori. Per le collezioni vengono utilizzati i generics.
Pro:
Contro: