Dog d = (Dog)Animal; //Compiles but fails at runtime
Aquí están diciendo al compilador "Confía en mí. Sé d
que realmente está refiriendo a un objeto Dog
", aunque no lo es. Recuerde compilador se ve obligado a confiar en nosotros cuando hacemos un abatido.
El compilador sólo conoce el tipo de referencia declarado. La JVM en el tiempo de ejecución sabe qué es realmente el objeto.
Así que cuando la JVM en el tiempo de ejecución se da cuenta de que el Dog d
se refiere en realidad a una Animal
y no un objeto Dog
que dice. Oye ... le mentiste al compilador y arroja un gran gordo ClassCastException
.
Por lo tanto, si está realizando un downcasting, debe utilizar la prueba instanceof
para evitar atornillar.
Ahora una pregunta viene a nuestra mente. ¿Por qué demonios el compilador está permitiendo el downcast cuando eventualmente lanzará un java.lang.ClassCastException
?
La respuesta es que todo el compilador puede hacer es verificar que los dos tipos están en el mismo árbol de herencia, así que dependiendo de lo que sea de código podría haber llegado antes los abatidos, es posible que animal
es de tipo dog
.
El compilador debe permitir todo lo que pueda funcionar en el tiempo de ejecución.
considere el siguiente código snipet:
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;
}
Sin embargo, si el compilador está seguro de que el reparto sería posible sin el trabajo, compilación fallará. ES DECIR. Si intenta convertir los objetos en diferentes herencia jerarquías
String s = (String)d; // ERROR : cannot cast for Dog to String
A diferencia downcasting, upcasting funciona de manera implícita, porque cuando se upcast está restringiendo implícitamente el número de método que se puede invocar, como opuesta a downcasting, que implica que más adelante, es posible que desee invocar un método más específico.
Dog d = new Dog(); Animal animal1 = d; // Works fine with no explicit cast Animal animal2 = (Animal) d; // Works fine with n explicit cast
Tanto la conversión hacia arriba anterior funcionará bien sin ninguna excepción, porque un perro es-A animal, anithing un animal puede hacer, un perro puede hacer. Pero no es verdad vica-versa.
USTED le está diciendo al compilador que NO detecte el error. – Mauricio