Casting Objects and the instanceof Operator

Paul Ngugi - Jun 10 - - Dev Community

One object reference can be typecast into another object reference. This is called casting object. In the preceding section, the statement

m(new Student());

assigns the object new Student() to a parameter of the Object type. This statement is equivalent to

Object o = new Student(); // Implicit casting
m(o);

The statement Object o = new Student(), known as implicit casting, is legal because an instance of Student is an instance of Object.

Suppose you want to assign the object reference o to a variable of the Student type using the following statement:

Student b = o;

In this case a compile error would occur. Why does the statement Object o = new Student() work but Student b = o doesn’t? The reason is that a Student object is always an instance of Object, but an Object is not necessarily an instance of Student. Even though you can see that o is really a Student object, the compiler is not clever enough to know it. To tell the compiler that o is a Student object, use explicit casting. The syntax is similar to the one used for casting among primitive data types. Enclose the target object type in parentheses and place it before the object to be cast, as follows:

Student b = (Student)o; // Explicit casting

It is always possible to cast an instance of a subclass to a variable of a superclass (known as upcasting), because an instance of a subclass is always an instance of its superclass. When casting an instance of a superclass to a variable of its subclass (known as downcasting), explicit casting must be used to confirm your intention to the compiler with the (SubclassName) cast notation. For the casting to be successful, you must make sure that the object to be cast is an instance of the subclass. If the superclass object is not an instance of the subclass, a runtime ClassCastException occurs. For example, if an object is not an instance of Student, it cannot be cast into a variable of Student. It is a good practice, therefore, to ensure that the object is an instance of another object before attempting a casting. This can be accomplished by using the instanceof operator. Consider the following code:

Object myObject = new Circle();
... // Some lines of code
/** Perform casting if myObject is an instance of Circle */
if (myObject instanceof Circle) {
System.out.println("The circle diameter is " +
((Circle)myObject).getDiameter());
...
}

You may be wondering why casting is necessary. The variable myObject is declared Object. The declared type decides which method to match at compile time. Using myObject.getDiameter() would cause a compile error, because the Object class does not have the getDiameter method. The compiler cannot find a match for myObject.getDiameter(). Therefore, it is necessary to cast myObject into the Circle type to tell the compiler that myObject is also an instance of Circle.

Why not define myObject as a Circle type in the first place? To enable generic programming, it is a good practice to define a variable with a supertype, which can accept an object of any subtype. instanceof is a Java keyword. Every letter in a Java keyword is in lowercase.

To help understand casting, you may also consider the analogy of fruit, apple, and orange, with the Fruit class as the superclass for Apple and Orange. An apple is a fruit, so you can always safely assign an instance of Apple to a variable for Fruit. However, a fruit is not necessarily an apple, so you have to use explicit casting to assign an instance of Fruit to a variable of Apple.

The program below demonstrates polymorphism and casting. The program creates two objects (lines 7–8), a circle and a rectangle, and invokes the displayObject method to display them (lines 11–12). The displayObject method displays the area and diameter if the object is a circle (line 17), and the area if the object is a rectangle (lines 21).

Image description

The displayObject(Object object) method is an example of generic programming. It can be invoked by passing any instance of Object.

The program uses implicit casting to assign a Circle object to object1 and a Rectangle object to object2 (lines 7–8), then invokes the displayObject method to display the information on these objects (lines 11–12).

In the displayObject method (lines 16–24), explicit casting is used to cast the object to Circle if the object is an instance of Circle, and the methods getArea and getDiameter are used to display the area and diameter of the circle.

Casting can be done only when the source object is an instance of the target class. The program uses the instanceof operator to ensure that the source object is an instance of the target class before performing a casting (line 17).

Explicit casting to Circle (lines 18, 19) and to Rectangle (line 22) is necessary because the getArea and getDiameter methods are not available in the Object class.

The object member access operator (.) precedes the casting operator. Use parentheses to ensure that casting is done before the . operator, as in

((Circle)object).getArea();

Casting a primitive type value is different from casting an object reference. Casting a primitive type value returns a new value. For example:

int age = 45;
byte newAge = (byte)age; // A new value is assigned to newAge

However, casting an object reference does not create a new object. For example:

Object o = new Circle();
Circle c = (Circle)o; // No new object is created

Now reference variables o and c point to the same object.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .