Le mécanisme de conversion de types en Java (type casting) permet au programmeur de transformer explicitement ou implicitement une valeur d'un type à un autre. Historiquement, cette fonctionnalité est héritée du C et C++, mais en Java, elle est limitée pour augmenter la sécurité des types et prévenir les bogues cachés liés au débordement ou à la perte de données.
Problème réside dans la possibilité de déclencher une ClassCastException lors de la conversion de types référentiels, ainsi que dans la perte de précision lors de la conversion de types primitifs, par exemple, lors du passage de double à int. Des erreurs logiques peuvent survenir lors du "downcasting" (conversion vers un type dérivé) si l'instance n'appartient pas à cette classe.
Solution consiste en une séparation stricte :
Exemple de code pour les types primitifs :
int i = 100; long l = i; // conversion implicite (int -> long) double d = l; // implicite (long -> double) int i2 = (int) d; // conversion explicite (perte de la partie fractionnaire)
Exemple de code pour les types référentiels :
Object obj = "Hello"; // upcasting, implicitement String s = (String) obj; // downcasting, explicitement
Caractéristiques clés :
Le compilateur Java peut-il prévenir toute conversion de type erronée ?
Réponse : Non, le compilateur ne détecte que les erreurs évidentes au moment de la compilation. Si la conversion est possible dans la structure des types (par exemple, Object -> String), mais que la variable contient réellement un objet d'un type incompatible, l'erreur se manifestera uniquement à l'exécution avec une ClassCastException.
Integer hérite-t-il de Long, et peut-on écrire Integer i = (Integer) someLong ?
Réponse : Non, Integer et Long sont des classes d'emballage indépendantes, il n'est pas possible de faire du downcasting entre elles. Elles héritent toutes deux de Number, mais pas l'une de l'autre. La conversion sous la forme (Integer) (Object) 1L; provoquera une ClassCastException.
Lors de la conversion explicite de float en int, la partie fractionnaire est-elle arrondie ?
Réponse : Non, la partie fractionnaire est simplement supprimée sans arrondi :
float f = 3.99f; int i = (int) f; // i == 3, pas 4
Un développeur reçoit une collection Object, convertit chaque élément à son type, mais ne vérifie pas instanceof. Le projet échoue systématiquement avec une ClassCastException lors de données incorrectes.
Avantages :
Inconvénients :
Toutes les opérations de downcasting sont effectuées à l'intérieur d'un if (obj instanceof TargetType) avec un traitement explicite des erreurs. Les génériques sont utilisés pour les collections.
Avantages :
Inconvénients :