Upcasting: you can assign a reference variable to a super-type reference variable explicitly or implicitly. This is inherently safe operation because the assignment restricts the access capabilities of the new variable.
Downcasting: if the type of a variable x is a super-type (parent class) and if x refers to an object which has the same type than a sub-type (child class), then you can explicitly cast x to this sub-type. You can then access the sub-type's members with this new reference variable.
Eg.
class Animal {
public void eat(int quantityFood){
}
}
class Cat extends Animal {
// Override the method eat()
public void eat(int quantityFood){
}
}
// upcasting of Cat to Animal (implicit casting)
// as a Cat is an Animal
Animal ah = new Cat();
// Runs 'Cat' version of "eat()"
ah.eat();
// downcasting of Animal to Cat (explicit casting)
Cat c = (Cat) ah;
In this example, we say that the reference variable "ah" has a reference type "Animal" and refers to an an object type "Cat". Because of this property we can "downcast" it back to "Cat" as above.
Not allowed downcastings:
Eg 1.
// As the classes "Cat" and "Animal" are part of
// the same hierarchy tree ("Cat" is a subclass
// of "Animal"), this casting will compile but during
// the runtime JVM will throw the exception "java.lang.ClassCastException".
Animal a = new Animal();
Cat h = (Cat) a;
Eg 2.
Animal a = new Animal(); // This will not compile because "String" and "Animal" // are not part of the same hierarchy tree String sa = (String) a;
