Skip to content Skip to navigation

OpenStax_CNX

You are here: Home » Content » Java OOP: Polymorphism and the Object Class

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Java OOP: Polymorphism and the Object Class

Module by: R.G. (Dick) Baldwin. E-mail the author

Summary: Baldwin discusses the use of the Object class as a completely generic type for storing references to objects of subclass types, and explains how that results in a very useful form of runtime polymorphism.

Note: You are viewing an old version of this document. The latest version is available here.

Preface

This module is one of a series of modules designed to teach you about the essence of Object-Oriented Programming (OOP) using Java.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the listings while you are reading about them.

Listings

Preview

What is polymorphism?

If you have studied the earlier modules in this collection, you should already know what polymorphism is, how it is implemented in Java, the three distinct forms of polymorphism in Java, etc.

I discussed runtime polymorphism implemented through method overriding and class inheritance in a previous module. However, before leaving that topic, I need to discuss an important special case.

In this module, I will discuss the use of the Object class as a completely generic type for storing references to objects of subclass types, and will explain how that results in a very useful form of runtime polymorphism.

I will briefly discuss the default versions of eleven methods defined in the Object class, and will explain that in many cases, those default versions are meant to be overridden.

Discussion and sample code

The Java Collections Framework

Java supports a framework, known as the Java Collections Framework, which you can read about in other tutorials on my web site at http://www.dickbaldwin.com/toc.htm .

Without getting into a lot of detail, the framework provides several concrete implementations of interfaces with names like list , set , and map .

The classes that provide the implementations have names like LinkedList , TreeSet , ArrayList , Vector , and Hashtable . As you might recognize, the framework satisfies the requirements for what we might refer to as classical data structures.

Not the purpose ...

However, it is not the purpose of this module to discuss either the Java Collections Framework, or classical data structures. Rather, they are mentioned here simply because the framework provides a good example of the use of the Object class as a generic type for runtime polymorphic behavior.

(Also beyond the scope of this module is the fact that the framework provides an outstanding example of the implementation of polymorphic behavior through the use of the Java interface. The use of the Java interface is a topic for a future module)

References of type Object

The classes mentioned above store references to objects created according to interfaces, contracts, and stipulations provided by the framework. More importantly for the purposes of this module, those references are stored as type Object .

(See my tutorial titled Generics in J2SE 5.0 at http://www.developer.com/java/other/article.php/3495121/Generics-in-J2SE-50.htm for additional information on this topic.)

The Object type is a completely generic type, which can be used to store a reference to any object that can be instantiated in Java.

Methods defined in the Object class

In an earlier module, I told you that the class named Object defines default versions of the following methods:

  • clone()
  • equals(Object obj)
  • finalize()
  • getClass()
  • hashCode()
  • notify()
  • notifyAll()
  • toString()
  • wait()
  • wait(long timeout)
  • wait(long timeout, int nanos)

Every class inherits these methods

Because every class is either a direct or indirect subclass of Object , every class in Java, (including new classes that you define) , inherits these eleven methods.

To be overridden ...

Some of these eleven methods are intended to be overridden for various purposes.

Calling methods of the Object class

You can store a reference to any object in a reference variable of type Object .

If you have studied the previous modules in this collection, you also know how runtime polymorphism based on class inheritance works.

Given the above, you should know that you can call any of the methods defined in the Object class on any reference to any object stored in a reference variable of type Object (including the references stored in the concrete implementations of the Java Collections Framework) .

And the behavior will be ...

If the class from which that object is instantiated inherits or defines an overridden version of one of the methods in the above list, calling that method on the reference will cause the overridden version to be executed.

Otherwise, calling that method on the reference will cause the default version defined in the Object class to be executed.

A sample program

This is illustrated in the program named Poly04 , which you can view in its entirety in Listing 7 near the end of this module.

For purposes of illustration, this program deals specifically with the method named toString from the above list, but it could deal just as well with other non-final methods in the list.

The class named A

Listing 1 defines a class named A , which extends the class named Object (recall that it is not necessary to explicitly show that a class extends Object ).

Listing 1: Definition of the class named A.

class A extends Object{
  //This class is empty
}//end class A

Does not override the toString method

The most important thing to note about the class named A is that it does not override any of the methods that it inherits from the class named Object .

For purposes of this illustration, we will say that it inherits the default version of the method named toString , from the class named Object . (We will see an example of the behavior of the default version of the toString method shortly.)

The class named B

Listing 2 contains the definition of a class named B . This class extends the class named A .

Listing 2: Definition of the class named B.

class B extends A{
  public String toString(){
    return "toString in class B";
  }//end overridden toString()
}//end class B

Overrides the toString method

Of particular interest, for purposes of this module, is the fact that the class named B does override the inherited t oString method.

(The class named B inherits the default version of the method, because its superclass named A , which extends Object , does not override the toString method.)

Purpose of the toString method

The purpose of the toString method is to return a reference to an object of the class String that represents an object instantiated from a class that overrides the method.

Here is part of what Sun has to say about the toString method:

"Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method."

Behavior of the overridden version

As you can see, I didn't follow Sun's advice very closely in this program. To begin with, I didn't override the toString method in the class named A .

Further, the behavior of my overridden version of the toString method in the class named B doesn't provide much in the way of a textual representation of an object instantiated from class B .

My overridden version simply returns a reference to a String object, containing text that indicates that the overridden version of the method defined in the class named B has been executed. (Of course, there wasn't much about an object instantiated from the class named B that could be represented in a textual way.)

Will be useful later

The reference to the String object returned by the overridden version of the toString method will prove useful later when we need to determine which version of the method is actually executed.

The class named C

Listing 3 shows the definition of a class named C , which extends the class named B , and overrides the method named toString again. (A non-final method can be overridden by every class that inherits it, resulting in potentially many different overridden versions of a method in a class hierarchy.)

Listing 3: Definition of the class named C.

class C extends B{
  public String toString(){
    return "toString in class C";
  }//end overridden toString()
}//end class B

Behavior of overridden version

The behavior of this overridden version of the method is similar to, but different from the overridden version in the class B .

In this case, the method returns a reference to a String object that can be used to confirm that this overridden version of the method has been executed.

The driver class

Finally, Listing 4 shows the beginning of the driver class named Poly04 .

Listing 4: Beginning of the class named Poly04.

public class Poly04{
  public static void main(String[] args){
    Object varA = new A();
    String v1 = varA.toString();
    System.out.println(v1);

A new object of the class A

The main method of the driver class begins by instantiating a new object of the class A , and saving the object's reference in a reference variable of type Object , named varA .

Call toString method on the reference

Then the code in Listing 4 calls the toString method on the reference variable named varA , saving the returned reference to the String in a reference variable of type String named v1 .

Display the returned String

Finally, that reference is passed to the println method, causing the String returned by the toString method to be displayed on the computer screen.

(In a future module, you will learn that some of the code in Listing 4 is redundant.)

This causes the following text to be displayed on the computer screen:

A@111f71 

Pretty ugly, huh?

Nowhere does our program explicitly show the creation of any text that looks anything like this. Where did it come from?

Default toString behavior

What you are seeing here is the String produced by the default version of the toString method, as defined by the class named Object .

Class A does not override toString

Recall that our new class named A does not override the toString method. Therefore, when the toString method is called on a reference to an object of the class A , the default version of the method is executed, producing output similar to that shown above .

What does Sun have to say?

Here is more of what Sun has to say about the default version of the toString method

"The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object."

You should recognize this as a description of the output produced by calling the toString method on the reference to the object of the class A . That explains the ugliness of the screen output shown above (hexadecimal representations of hashcodes are usually pretty ugly) .

A new object of the class B

Now consider the code shown in Listing 5 , which instantiates a new object of the class named B , and stores the object's reference in a reference variable of type Object .

Listing 5: A new object of the class named B.

Object varB = new B();
    String v2 = varB.toString();
    System.out.println(v2);

Call toString and display the result

The code in Listing 5 calls the toString method on the reference of type Object , saving the returned reference in the reference variable named v2 . (Recall that the toString method is overridden in the class named B.)

As before, the reference is passed to the println method, which causes the following text to be displayed on the computer screen.

toString in class B 

Do you recognize this?

You should recognize this as the text that was encapsulated in the String object by the overridden version of the toString method defined in the class named B .

Overridden version of toString was executed

This verifies that even though the reference to the object of the class B was stored in a reference variable of type Object , the overridden version of the toString method defined in the class named B was executed (instead of the default version defined in the class named Object ) . This is a good example of runtime polymorphic behavior , as described in a previous module.

As you learned in the previous module, the selection of a method for execution is based on the actual type of object whose reference is stored in a reference variable, and not on the type of the reference variable on which the method is called.

An object of the class C

Finally, the code in Listing 6

  • Instantiates a new object of the class C .
  • Stores the object's reference in a reference variable of type Object .
  • Calls the toString method on the reference.
  • Displays the returned string on the computer screen.

Listing 6: A new object of the class named C.

Object varC = new C();
    String v3 = varC.toString();
    System.out.println(v3);

What will the output look like?

By now, you should know what to expect in the way of text appearing on the computer screen. The code in Listing 6 causes the following text to be displayed:

toString in class C 

Overridden version of toString was called

This confirms what you should already have known by now. In particular, even though the reference to the object of the class C is stored in a reference variable of type Object , the overridden version of the toString method defined in the class named C was executed. Again, this is runtime polymorphic behavior based on class inheritance and method overriding.

No downcasting was required

It is also very important to note that no downcasting was required in order to call the toString method in any of the cases shown above.

Because a default version of the toString method is defined in the Object class, the toString method can be called without a requirement for downcasting on a reference to any object stored in a variable of type Object . This holds true for any of the eleven methods defined in the class named Object (although some of those methods are declared final and therefore may not be overridden) .

Summary

Polymorphism manifests itself in Java in the form of multiple methods having the same name.

From a practical programming viewpoint, polymorphism manifests itself in three distinct forms in Java:

  • Method overloading
  • Method overriding through class inheritance
  • Method overriding through the Java interface

In this module, I have continued my discussion of the implementation of polymorphism using method overriding through class inheritance, and have concentrated on a special case in that category.

More specifically, in this module, I have discussed the use of the Object class as a completely generic type for storing references to objects of subclass types, and have explained how that results in a very useful form of runtime polymorphism. .

I briefly mentioned the default version of the eleven methods defined in the Object class, and explained that in some cases, those default versions are meant to be overridden.

I provided a sample program that illustrates the overriding of the toString method, which is one of the eleven methods defined in the Object class.

What's next?

In the next module, I will embark on an explanation of runtime polymorphic behavior based on the Java interface and method overriding.

In my opinion, this is one of the most important concepts in Java OOP, and the one that seems to give students the greatest amount of difficulty.

Miscellaneous

This section contains a variety of miscellaneous information.

Note:

Housekeeping material
  • Module name: OOP 101, Polymorphism and the Object Class
  • File: Java1614.htm
  • Published: March 13, 2002
  • Revised: July 26, 2012
  • Keywords:
    • runtime polymorphism
    • Object class
    • toString method

Note:

Disclaimers:

Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.

I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.

In the past, unknown individuals have misappropriated copies of my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I receive no compensation for those sales and don't know who does receive compensation. If you purchase such a book, please be aware that it is a bootleg copy of a module that is freely available on cnx.org.

Affiliation :: I am a professor of Computer Information Technology at Austin Community College in Austin, TX.

Complete program listing

A complete listing of the program is shown in Listing 7 below.

Listing 7: Complete program listing.

/*File Poly04.java
Copyright 2002, R.G.Baldwin

This program illustrates polymorphic 
behavior

Program output is:
  
A@111f71
toString in class B
toString in class C
**************************************/

class A extends Object{
  //This class is empty
}//end class A
//===================================//

class B extends A{
  public String toString(){
    return "toString in class B";
  }//end overridden toString()
}//end class B
//===================================//

class C extends B{
  public String toString(){
    return "toString in class C";
  }//end overridden toString()
}//end class B
//===================================//

public class Poly04{
  public static void main(String[] args){
    Object varA = new A();
    String v1 = varA.toString();
    System.out.println(v1);
    
    Object varB = new B();
    String v2 = varB.toString();
    System.out.println(v2);
    
    Object varC = new C();
    String v3 = varC.toString();
    System.out.println(v3);

  }//end main
}//end class Poly04

-end-

Content actions

Download module as:

PDF | EPUB (?)

What is an EPUB file?

EPUB is an electronic book format that can be read on a variety of mobile devices.

Downloading to a reading device

For detailed instructions on how to download this content's EPUB to your specific device, click the "(?)" link.

| More downloads ...

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks