una superclase sintaxis simple polimorfismo para herencia ejercicios ejemplos ejemplo java casting classcastexception

superclase - super en java



lanzamiento explícito de superclase a subclase (6)

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; } }

La asignación Dog dog = (Dog) animal; no genera un error de compilación, pero en el tiempo de ejecución genera una ClassCastException . ¿Por qué el compilador no puede detectar este error?


Al usar un elenco básicamente le estás diciendo al compilador "créeme. Soy un profesional, sé lo que estoy haciendo y sé que aunque no puedes garantizarlo, te digo que esta variable animal es definitivamente va a ser un perro ".

Como el animal no es realmente un perro (es un animal, puedes hacer Animal animal = new Dog(); y sería un perro) el VM lanza una excepción en el tiempo de ejecución porque has violado esa confianza (le dijiste el compilador todo estaría bien y no lo es!)

El compilador es un poco más inteligente que simplemente aceptar ciegamente todo, si intentas lanzar objetos en diferentes jerarquías de herencia (por ejemplo, lanzar un Perro a una cadena), el compilador se lo devolverá porque sabe que posiblemente nunca funcionará.

Debido a que esencialmente está evitando que el compilador se queje, cada vez que realice un colado es importante verificar que no cause una ClassCastException utilizando instanceof en una sentencia if (o algo por el estilo).


Como se explicó, no es posible. Si desea utilizar un método de la subclase, evalúe la posibilidad de agregar el método a la superclase (puede estar vacío) y llame desde las subclases obteniendo el comportamiento que desea (subclase) gracias al polimorfismo. Por lo tanto, cuando llame a d.method () la llamada tendrá éxito sin moldear, pero en caso de que el objeto no sea un perro, no habrá un problema


El código genera un error de compilación porque tu tipo de instancia es un Animal:

Animal animal=new Animal();

Downcasting no está permitido en Java por varias razones. Mira here para más detalles.


Para evitar este tipo de ClassCastException, si tiene:

class A class B extends A

Puede definir un constructor en B que tome un objeto de A. De esta manera podemos hacer el "molde", por ejemplo:

public B(A a) { super(a.arg1, a.arg2); //arg1 and arg2 must be, at least, protected in class A // If B class has more attributes, then you would initilize them here }


Porque teóricamente Animal animal puede ser un perro:

Animal animal = new Dog();

En general, downcasting no es una buena idea. Debes evitarlo. Si lo usa, es mejor que incluya un cheque:

if (animal instanceof Dog) { Dog dog = (Dog) animal; }


Dog d = (Dog)Animal; //Compiles but fails at runtime

Aquí le estás diciendo al compilador "Créeme. Sé que realmente se está refiriendo a un objeto Dog " aunque no lo es. Recuerde que el compilador se ve obligado a confiar en nosotros cuando hacemos un downcast .

El compilador solo conoce el tipo de referencia declarado. La JVM en tiempo de ejecución sabe qué es realmente el objeto.

Entonces, cuando la JVM en el tiempo de ejecución se da cuenta de que el Dog d está refiriendo realmente a un objeto Animal y no a un Dog , dice. Oye ... mentiste al compilador y arrojó una gran ClassCastException .

Por lo tanto, si está realizando un downcasting, debe usar la prueba instanceof para evitar atornillar.

if (animal instanceof Dog) { Dog dog = (Dog) animal; }

Ahora surge una pregunta en nuestra mente. ¿Por qué demonios el compilador está permitiendo el downcast cuando eventualmente lanzará java.lang.ClassCastException ?

La respuesta es que todo lo que el compilador puede hacer es verificar que los dos tipos estén en el mismo árbol de herencia, por lo que dependiendo de cualquier código que haya aparecido antes del downcast, es posible que el animal sea ​​de tipo dog .

El compilador debe permitir cosas que posiblemente funcionen en 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 molde no funcionaría, la compilación fallará. IE Si intentas lanzar objetos en diferentes jerarquías de herencia

String s = (String)d; // ERROR : cannot cast for Dog to String

A diferencia del downcasting, el upcasting funciona implícitamente porque cuando edificas, implícitamente estás restringiendo el número de métodos que puedes invocar, como opuesto a downcasting, lo que implica que más tarde, podrías 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

Los dos upcast anteriores funcionarán bien sin excepción, porque un perro IS-A Animal, un animal que puede hacer, un perro puede hacerlo. Pero no es verdad vica-versa.