public class Animal {
public void eat() {}
}
public class Dog extends Animal {
public void eat() {}
public void main(String[] args) {
Animal animal = new Animal();
Dog dog = (Dog) animal;
}
}
L'affectation Dog dog = (Dog) animal;
ne génère pas d'erreur de compilation, mais au moment de l'exécution, elle génère un fichier ClassCastException
. Pourquoi le compilateur ne peut-il pas détecter cette erreur?
java
casting
classcastexception
Saravanan
la source
la source
Réponses:
En utilisant un casting, vous dites essentiellement au compilateur "faites-moi confiance. Je suis un professionnel, je sais ce que je fais et je sais que même si vous ne pouvez pas le garantir, je vous dis que cette
animal
variable est définitivement va être un chien. "Puisque l'animal n'est pas réellement un chien (c'est un animal, vous pourriez le faire
Animal animal = new Dog();
et ce serait un chien), la VM lève une exception à l'exécution parce que vous avez violé cette confiance (vous avez dit au compilateur que tout irait bien et c'est ne pas!)Le compilateur est un peu plus intelligent que d'accepter tout aveuglément, si vous essayez de convertir des objets dans différentes hiérarchies d'héritage (transtyper un chien en chaîne par exemple), le compilateur vous le renverra car il sait que cela ne pourrait jamais fonctionner.
Étant donné que vous empêchez essentiellement le compilateur de se plaindre, chaque fois que vous lancez un cast, il est important de vérifier que vous ne provoquerez pas de
ClassCastException
en utilisantinstanceof
une instruction if (ou quelque chose à cet effet.)la source
Dog
ne s'étendre à partirAnimal
!Parce que théoriquement
Animal animal
peut être un chien:En règle générale, le downcasting n'est pas une bonne idée. Vous devriez l'éviter. Si vous l'utilisez, vous feriez mieux d'inclure un chèque:
la source
Afin d'éviter ce type d'exception ClassCastException, si vous avez:
Vous pouvez définir un constructeur en B qui prend un objet de A. De cette façon, nous pouvons faire le "cast" par exemple:
la source
Élaboration de la réponse donnée par Michael Berry.
Dog d = (Dog)Animal; //Compiles but fails at runtime
Ici, vous dites au compilateur "Faites-moi confiance. Je sais que cela
d
fait vraiment référence à unDog
objet" bien que ce ne soit pas le cas. N'oubliez pas que le compilateur est obligé de nous faire confiance lorsque nous faisons un downcast .Ainsi, lorsque la JVM au moment de l'exécution comprend que le
Dog d
fait référence àAnimal
unDog
objet et non à un objet, il le dit. Hé ... tu as menti au compilateur et jette un gros morceauClassCastException
.Donc, si vous êtes abattu, vous devez utiliser le
instanceof
test pour éviter de vous tromper.if (animal instanceof Dog) { Dog dog = (Dog) animal; }
Maintenant, une question nous vient à l'esprit. Pourquoi diable le compilateur autorise-t-il le downcast quand finalement il va lancer un
java.lang.ClassCastException
?La réponse est que tout ce que le compilateur peut faire est de vérifier que les deux types sont dans la même arborescence d'héritage, donc en fonction du code qui aurait pu venir avant le downcast, il est possible qu'il
animal
soit de typedog
.Considérez l'extrait de code suivant:
Cependant, si le compilateur est sûr que la distribution ne fonctionnerait pas, la compilation échouera. IE Si vous essayez de convertir des objets dans différentes hiérarchies d'héritage
String s = (String)d; // ERROR : cannot cast for Dog to String
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 upcast ci-dessus fonctionneront très bien sans aucune exception car un chien est un animal, tout comme un animal peut le faire, un chien peut le faire. Mais ce n'est pas vrai vica-versa.
la source
Le code génère une erreur de compilation car votre type d'instance est un animal:
Le downcasting n'est pas autorisé en Java pour plusieurs raisons. Voir ici pour plus de détails.
la source
Comme expliqué, ce n'est pas possible. Si vous souhaitez utiliser une méthode de la sous-classe, évaluez la possibilité d'ajouter la méthode à la superclasse (peut être vide) et appelez depuis les sous-classes en obtenant le comportement souhaité (sous-classe) grâce au polymorphisme. Donc quand vous appelez d.method () l'appel réussira sans lancer, mais au cas où l'objet ne serait pas un chien, il n'y aura pas de problème
la source
Pour développer la réponse de @Caumons:
Jetez maintenant un œil à cette solution.
Maintenant, nous testons l'application:
Et voici le résultat :
Maintenant, vous pouvez facilement ajouter de nouveaux champs à la classe père sans vous soucier de vos codes enfants à casser;
la source