5.2 Polymorphism & CastingHomepage « Java5 Certification « 5.2 Polymorphism & Casting
In this lesson we explain polymorphism and how we use it in the Java language before looking at object reference casting and determine when casting will be necessary whilst recognizing compiler vs. runtime errors, related to it.
Lets take a look at the points outlined at the Oracle Website for this part of the certification.
- Section 5: OO Concepts
- Given a scenario, develop code that demonstrates the use of polymorphism. Further, determine when casting will be necessary and recognize compiler vs. runtime errors related to object reference casting.
Polymorphism, which roughly translated from the Greek means 'the ability to assume different forms'. So what does this mean for us Java programmers? To explain this we will refresh our memory about how we create an object:

So lets go through the three step process above:
- Declaration - Here. we declare a reference type named
garbage
of typeGarbage
and the JVM allocates space for it. - Creation - Tells the JVM to allocate space on The Heap for a new
Garbage
object. - Assignment - Assign the new
Garbage
object to the reference typegarbage
.
The reference type and the object type are the same.
Polymorphic Method Invocation
Top
With polymorphism when you declare the reference type in the declaration, it can be from a superclass of the object we are creating. Or looking from a different perspective, when creating an object, we can use any supertype from a class that we have extended. The compiler has no problem with this but the power of polymorphism happens at runtime through the concept of virtual method invocation. This concept is the dynamic selection of overridden methods at runtime based on the actual object type, rather than the reference type. This only applies to instance methods, everything else uses the reference type at runtime.

So what does this give us I hear you ask? Well we can use the supertype for reference type declaration when instantiating our objects, safe in the knowledge that the JVM will use the actual object created to invoke the correct overridden methods of the subtypes at runtime.
See the OO Concepts - Polymorphism lesson for details.
Deeper Into Polymorphism
Top
We can pass a polymorphic interface type as an argument and return a polymorphic interface type as well. An implemented abstract type is exactly the same as an overridden method type and so will use polymorphic method invocation to dynamically invoke the method of the the actual object type at runtime. This means we can group together objects from different hierarchies under the umbrella of the interface type as the reference type knowing the correct object will be always be invoked at runtime.
See the OO Concepts - Interfaces lesson for details.
Polymorphic Rules
Top
There are some things to remember with regards to reference variables when using polymorphism:
- A reference variable can only refer to one type and once declared is immutable although the object it refers to can change.
- Like any other non
final
variables, reference variable can be reassigned to other objects. - The assigned reference variable can refer to the same type as the declared reference variable or any subtype of the declared reference variable.
- Instance methods use the concept of virtual method invocation to dynamically invoke overridden methods at runtime based on the actual object type, rather than the declared reference type. This only applies to instance methods, everything else uses the declared reference type at runtime.
- Reference variables can be declared as a class type or an interface type and if the reference variable is declared as an interface type it can reference any object of any class implementing the interface.
Object Reference Casting
Top
In this part of the lesson we look at casting with regards to polymorphic types and when to use it. Lets get the terminology out of the way first:
- downcasting - casting down the inheritance tree and has to be coded explicitly.
- upcasting - casting up the inheritance tree and is implicit although we can code this ourselves.
We will look at some code to see when we need downcast and what happens when we cast wrongly or don't cast at all:
/*
Casting Examples
*/
class A {
void methodA() {
System.out.println("method A class A");
}
}
class B extends A {
void methodA() {
System.out.println("method A class B");
}
void methodB() {
System.out.println("method B class B");
}
}
/*
Test classes for casting
*/
public class CastTest1 {
public static void main (String[] args) {
A a = new A();
B b = (B) a;
}
}
public class CastTest2 {
public static void main (String[] args) {
B b = new B();
A a1 = b;
A a2 = (A) b;
}
}
public class CastTest3 {
public static void main (String[] args) {
A [] aArray = { new A(), new B() };
for(A a : aArray) {
a.methodA();
if (a instanceof B) {
a.methodB();
}
}
}
}
public class CastTest4 {
public static void main (String[] args) {
A [] aArray = { new A(), new B() };
for(A a : aArray) {
a.methodA();
if (a instanceof B) {
B b = (B) a;
b.methodB();
}
}
}
}

The above screenshot shows the output of compiling our A
and B
classes and then trying to compile/run the CastTest1
, CastTest2
, CastTest3
and
CastTest4
classes.
When we compile CastTest1
it compiles fine as the compiler has to trust us when downcasting. When we run CastTest1
we get a ClassCastException
as b
is
actually an instance of class A
and supertypes know nothing about any subtypes.
When we compile and run CastTest2
it works fine, we are just showing implicit and explicit upcasting here.
The CastTest3
class doesn't compile as we haven't downcast our reference of a
and class A
doesn't have a method called methodB
.
The CastTest4
class compile and works as we downcast our reference of a
to a reference of class B
which does have a method called methodB
.
Related Java5 Tutorials
OO Concepts - Polymorphism
OO Concepts - Interfaces