SCJP Study Guide:
OO Concepts


Printer-friendly version Printer-friendly version | Send this 
article to a friend Mail this to a friend


Previous Next vertical dots separating previous/next from contents/index/pdf Contents
XyzWs SCJP Study Guide: Polymorphism and object reference casting

Polymorphism and object reference casting


Polymorphism is based on another Object-oriented concept: inheritance. Refer to SCJP Study Guide: Inheritance. Inheritance allows a subclass to override methods defined in its superclasses. Polymorphism makes sure that the correct method is called at runtime according to the actual run time type of the object. Refer to XyzWs Java FAQ: What is runtime polymorphism in java?.

Here we want to talk about the object reference casting when polymorphism occurs. Object reference casting is used when convertting between reference types. There are two types of casting operations:

  • Upcast operations, also called widening conversions in the JLS: convert a subclass reference to an ancestor class reference. This casting operation is normally automatic, since it's always safe and can be implemented directly by the compiler.
  • Downcast operations, also called narrowing conversions in the JLS: convert an ancestor class reference to a subclass reference. It requires an explicit casting.

    This casting operation creates execution overhead, since Java requires that the cast be checked at runtime to make sure that it's valid. If the referenced object is not an instance of either the target type for the cast or a subclass of that type, the attempted cast is not permitted and must throw a java.lang.ClassCastException.

Let's take a look at the following example:

public class Fruit {
}

public class Vegie{
}

public class Orange extends Friut {
  public static void main(String [] args) {
    Fruit f = new Orange();
    Orange o = new Orange();
    Vegie v = new Vegie();
   
    f = o; //widening conversion, doesn't need explicit casting
    o = (Orange)f; //narrowing conversion, need explicit casting 
    v = o; // illegal conversion
}

The compiler automatically handles the assignment f = o, since the types are compatible. That is, the type Fruit can "hold" the type Orange since a Orange is a Fruit. Such automatic cases are called conversions. The assignment, o=(Orange)f, however is not that obvious. A Fruit can be an Orange, but not necessary. The assignment is valid only when f is pointing to an Orange object, and a casting is required. The v=o is illegal, because a Vegie object is not related to an Orange object in any way.

The instanceof operator in Java allows you to determine the actual type of an object reference at run time. You can use the instanceof operator to check for the object type before doing the casting. However, it's not convenient to check the type every time before casting.

Here are some rule of thumb when doing the object reference casting:

  • When the two classes are not related to each other in any way, one neither inherits from the other, nor implements the same interface, there will be compile time error if trying to assign the object reference of one of the classes to the object reference of the other class.
  • Casts that are permitted at compile-time include casting any object to its own class or to one of its sub or superclass types or interfaces.
  • The compile-time rules cannot catch every invalid cast attempt. If the compile-time rules permit a cast, then additional, more stringent rules apply at runtime. These runtime rules basically require that the object being cast is compatible with the new type it is being cast to. Else, a ClassCastException is thrown at runtime.

A related automatic conversion works with interfaces.

Let's take a look at the following example:

  interface Sweet { ... } 
  class Fruit implements Sweet { ... } 

Then we see that a variable of type Fruit can be automatically converted to a variable of type Sweet. This makes perfect sense since a Fruit is Sweet.

  Fruit f; 
  Sweet s; 
  public void good_convert () { 
    s = f; // legal conversion from class type to interface type 
  } 

However, an attempt to convert from the interface type to the class type does not compile:

  public void bad_convert () { 
    f = s; // illegal conversion from interface type to class type 
  } 

Previous Next vertical dots separating previous/next from contents/index/pdf Contents

  |   |