class Animal { void eat() { System.out.println("Animal is eating"); } } class Dog extends Animal { void bark() { System.out.println("Dog is barking"); } } public class Example { public static void main(String[] args) { Animal myAnimal = new Dog(); // Downcasting requires explicit casting and may throw a ClassCastException if (myAnimal instanceof Dog) { Dog myDog = (Dog) myAnimal; myDog.eat(); // Accessing the base class method myDog.bark(); // Accessing the derived class method } } }// reference primitive, and its type SportsCar sc = new SportsCar(); Car c = sc; // upcasting is implicit, this is OK! sc.race(); // sc type is SportsCar, this is OK! c.race(); // c type is Car, will NOT compile! // Upcasting is implicit Car myCar = new SportsCar(); // upcasting Car myCar = sc; // upcasting is implicit Car myCar = (Car) sc; // (Car) is not necessary // Downcasting is explicit // potential ClassCastingException // b/c Java will not always be able to determine that you've specified the right types at compile time // So if you make a mistake you may encounter a run time error - hence Generics. SportsCar mySportsCar = (SportsCar) myCar; // potential ClassCastingException ((SportsCar) c).race(); // downcasting to allow specialized subclass methods