Élaboration de la réponse donnée par Michael Berry.
Dog d = (Dog)Animal; //Compiles but fails at runtime
Vous dites ici au compilateur : "Faites-moi confiance. Je sais que d
se réfère en réalité à un Dog
objet", alors que ce n'est pas le cas. Rappelez-vous que le compilateur est obligé de nous faire confiance lorsque nous faisons un downcast .
Le compilateur ne connaît que le type de référence déclaré. La JVM, au moment de l'exécution, sait ce qu'est réellement l'objet.
Ainsi, lorsque la JVM s'aperçoit, au moment de l'exécution, que l'élément Dog d
se réfère en fait à un Animal
et non un Dog
o Hey... tu as menti au compilateur et tu as lancé un bon gros ClassCastException
.
Par conséquent, si vous êtes en train de faire un downcasting, vous devez utiliser instanceof
pour éviter les erreurs.
if (animal instanceof Dog) { Dog dog = (Dog) animal; }
Une question nous vient à l'esprit. Pourquoi diable le compilateur autorise-t-il le downcast alors qu'il va finalement lancer un java.lang.ClassCastException
?
La réponse est que tout ce que le compilateur peut faire, c'est vérifier que les deux types se trouvent dans le même arbre d'héritage. avant le downcast, il est possible que le type animal
est du type dog
.
Le compilateur doit autoriser des choses qui pourraient fonctionner au moment de l'exécution.
Considérons l'extrait de code suivant :
public static void main(String[] args)
{
Dog d = getMeAnAnimal();// ERROR: Type mismatch: cannot convert Animal to Dog
Dog d = (Dog)getMeAnAnimal(); // Downcast works fine. No ClassCastException :)
d.eat();
}
private static Animal getMeAnAnimal()
{
Animal animal = new Dog();
return animal;
}
Cependant, si le compilateur est sûr que le cast ne fonctionnera pas, la compilation échouera. Par exemple, si vous essayez d'intégrer des objets dans des hiérarchies d'héritage différentes
String s = (String)d; // ERROR : cannot cast for Dog to String
Contrairement au downcasting, l'upcasting fonctionne de manière implicite, car lorsque vous upcaster, vous limitez implicitement le nombre de métadonnées. contrairement au downcasting, qui implique que plus tard, vous pourriez vouloir invoquer une méthode plus spécifique.
Dog d = new Dog(); Animal animal1 = d; // Works fine with no explicit cast Animal animal2 = (Animal) d; // Works fine with n explicit cast
Les deux cas de figure ci-dessus fonctionneront sans aucune exception car un chien est un animal, et tout ce qu'un animal peut faire, un chien peut le faire. Mais la réciproque n'est pas vraie.
55 votes
VOUS demandez au compilateur de NE PAS détecter l'erreur.