April 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

The Essence of OOP using Java, The this and super Keywords

  • August 6, 2002
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

Java Programming Notes # 1628


Preface

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

The first lesson in the series was entitled The Essence of OOP Using Java, Objects, and Encapsulation.  The previous lesson was entitled The Essence of OOP using Java, Array Objects, Part 3.

You may find it useful to open another copy of this lesson in a separate browser window.  That will make it easier for you to scroll back and forth among the different listings while you are reading about them.

For further reading, see my extensive collection of online Java tutorials at Gamelan.com. A consolidated index is available at Baldwin's Java Programming Tutorials.

Preview

This lesson explains the use of the keywords this and super.  Short sample programs illustrate how you can use these keywords for several purposes.

I will discuss and illustrate the use of the this keyword in the following situations:

  • To bypass local variables or parameters that hide member variables having the same name, in order to access the member variable.
  • To make it possible for one overloaded constructor to invoke another overloaded constructor in the same class.
  • To pass a reference to the current object to a method belonging to a different object (as in implementing callbacks, for example).
I will also discuss and illustrate the use of the super keyword in the following situations:
  • To bypass the overridden version of a method in a subclass and execute the version in the superclass.
  • To bypass a member variable in a subclass in order to access a member variable having the same name in a superclass.
  • To cause a constructor in a subclass to invoke a parameterized constructor in the immediate superclass.

Discussion and Sample Code

You already know quite a lot about OOP

By now you know that an object is an instance of a class.  You know that all variables and methods in Java must be contained in a class or an object.  You know that the three primary characteristics of an object-oriented programming language are:

  • encapsulation
  • inheritance
  • polymorphism.
If you have been studying this series of lessons on the Essence of OOP in Java, you already know quite a lot about OOP in general, and the implementation of OOP in Java in particular.

A few more important OOP/Java concepts

However, there are a few more important concepts that I haven't previously discussed in this series of lessons.  In this lesson, I will explain the use of the keywords this and super.

Data and methods

The class provides the plan from which objects are built. This plan defines the data that is to be stored in an object, and the methods for manipulating that data.  The data is variously referred to as data members, fields, and variables, depending on which book you are reading.

Non-static and static

The data can be further sub-divided into non-static and static, often referred to as instance variables and class variables respectively.

The methods are also often referred to as member methods, and they can also be static or non-static.  Static methods are often referred to as class methods while non-static methods are often referred to as instance methods.

Instance variables and instance methods

The class body contains the declarations for, and possibly the initialization of all data members (both class variables and instance variables) as well as the full definition of all methods.

In this lesson, we will be particularly interested in instance variables and instance methods.

Every class is a subclass of Object

By default, every class in Java extends (either directly or indirectly) the class named Object.  A new class may either extend Object, or extend another class that extends Object, or extend another class further down the inheritance hierarchy.

The immediate parent class of a new class is known as its superclass, and the new class is known as the subclass. (Sometimes we use the word superclass to indicate the collection of classes in the inheritance hierarchy from which a specific class is derived.)

If you do not specify the superclass for a new class, it will extend Object by default.

The extends keyword

The keyword extends is used in the class declaration to specify the immediate superclass of the new class using the syntax shown in Figure 1.
 

class NewClass extends SuperClassName{
  //body of class
}//end class definition

Figure 1

Inheritance

A class inherits the variables and methods of its superclass, and of the superclass of that class, etc., all the way back up the family tree to the single class Object, which is the root of all inheritance.

Thus, an object that is instantiated from a class contains all the instance variables and all the instance methods defined by that that class and defined by all its ancestors.

However, the methods may have been overridden one or more times along the way. Also, access to those variables and methods may have been restricted through the use of the public, private, and protected keywords.  (There is another access level, often referred to as package private, which is what you get when you don't use an access keyword.)

The this keyword

Every instance method in every object in Java receives a reference named this when the method is invoked.  The reference named this is a reference to the object on which the method was invoked.  It can be used for any purpose for which such a reference is needed.

Three common situations

There are at least three common situations where such a reference is needed:

  • To bypass local variables or parameters that hide member variables having the same name, in order to access the member variable.
  • To make it possible for one overloaded constructor to invoke another overloaded constructor in the same class.
  • To pass a reference to the current object to a method belonging to a different object (as in implementing callbacks, for example).
Hidden member variables

Normally, instance methods belonging to an object have direct access to the instance variables belonging to that object, and to the class variables belonging to the class from which that object was instantiated.  (Class methods never have access to instance variables or instance methods.)

Name can be duplicated

However, the name of a method parameter or constructor parameter can be the same as the name of an instance variable belonging to the object or a class variable belonging to the class.  It is also allowable for the name of a local variable to be the same as the name of an instance variable or a class variable.  In this case, the local variable or the parameter is said to hide the member variable having the same name.

Reference named this is passed to instance methods

As mentioned above, whenever an instance method is invoked on an object, a hidden reference named this is always passed to the method. The this reference always refers to the object on which the method was invoked.  This makes it possible for the code in the method to refer back to the object on which the method was invoked.

The reference named this can be used to access the member variables hidden by the local variables or parameters having of the same name.

The sample program named This01

The sample program shown in Listing 1 illustrates the use of the this reference to access a hidden instance variable named myVar and a hidden class variable named yourVar.
 

/*File This01.java 
Copyright 2002, R.G.Baldwin
Illustrates use of this keyword to 
access hidden member variables.

Tested using JDK 1.4.0 under Win2000

The output from this program is:

myVar parameter = 20
local yourVar variable = 1
Instance variable myVar = 5
Class variable yourVar = 10
**************************************/

class This01 {
  int myVar = 0;
  static int yourVar = 0;

  //Constructor with parameters named 
  // myVar and yourVar
  public This01(int myVar,int yourVar){
    this.myVar = myVar;
    this.yourVar = yourVar;
  }//end constructor
  //---------------------------------//
  
  //Method with parameter named myVar
  // and local variable named yourVar
  void myMethod(int myVar){
    int yourVar = 1; 
    System.out.println(
         "myVar parameter = " + myVar);
    System.out.println(
            "local yourVar variable = "
                            + yourVar);
    System.out.println(
           "Instance variable myVar = "
                         + this.myVar);
    System.out.println(
            "Class variable yourVar = "
                       + this.yourVar);
  }//end myMethod
  //---------------------------------//

  public static void main(
                        String[] args){
    This01 obj = new This01(5,10);
    obj.myMethod(20); 
  }//end main method
}//End This01 class definition.

Listing 1

The key points

The key points to observe in the program is Listing 1 are:

  • When the code refers to myVar or yourVar, the reference resolves to either an incoming parameter or to a local variable having that name.
  • When the code refers to this.myVar or this.yourVar, the reference resolves to the corresponding instance variable and class variable having that name.
To summarize this situation, every time an instance method is invoked, it receives a hidden reference named this.  That is a reference to the object on which the method was invoked.

The code in the method can use that reference to access any instance member of the object on which it was invoked, or any class member of the class from which the object was instantiated.

However, when class methods are invoked, they do not receive such a hidden reference, and therefore, they cannot refer to any instance members of any object instantiated from the class.  They can only access class members of the same class.

Invoking other constructors of the same class

Now I am going to discuss and illustrate the second common situation listed earlier.

A class can define two or more overloaded constructors having the same name and different argument lists.  Sometimes it is useful for one overloaded constructor to invoke another overloaded constructor in the same class.  When this is done, the constructor being invoked is referred to as though it were a method whose name is this, and whose argument list matches the argument list of the constructor being invoked.

The sample program named This02

This situation is illustrated in the program named This02 shown in Listing 2.
 

/*File This02.java 
Copyright 2002, R.G.Baldwin
Illustrates use of this keyword for one
overloaded constructor to access 
another overloaded constructor of the 
same class.

Tested using JDK 1.4.0 under Win2000

The output from this program is:

Instance variable myVar = 15
**************************************/

class This02 {
  int myVar = 0;

  public static void main(
                        String[] args){
    This02 obj = new This02();
    obj.myMethod(); 
  }//end main method
  //---------------------------------//
  
  //Constructor with no parameters
  public This02(){
    //Invoke parameterized constructor
    this(15);
  }//end constructor
  //---------------------------------//
  
  //Constructor with one parameter
  public This02(int var){
    myVar = var;
  }//end constructor
  //---------------------------------//
  
  //Method to display member variable
  // named myVar
  void myMethod(){
    System.out.println(
           "Instance variable myVar = "
                              + myVar);
  }//end myMethod

}//End This02 class definition.

Listing 2

Invoking a noarg constructor

Pay particular attention to the boldface code in Listing 2.  The main method instantiates a new object by applying the new operator to the noarg constructor for the class named This02. (The common jargon for a constructor that doesn't take any parameters is a noarg constructor.)

The noarg constructor invokes a parameterized constructor

The code in the noarg constructor uses the this keyword to invoke the other overloaded constructor, passing an int value of 15 as a parameter.

That constructor stores the value of the incoming parameter (15) in the instance variable named myVar.  Then control returns to the noarg constructor, which in turn returns control to the main method.  When control returns to the main method, the new object has been constructed, and the instance variable named myVar belonging to that object contains the value 15.

Display the value of the instance variable

The next statement in the main method invokes the method named myMethod on the object, which causes the value stored in the instance variable (15) to be displayed on the screen.

The most important statement

For purposes of this discussion, the most important statement in the program is the statement that reads:

this(15);

This is the statement used by one overloaded constructor to invoke another overloaded constructor.

Callbacks

An extremely important concept in programming is the third situation mentioned in the earlier list.  This is a situation where a method in one object invokes a method in another object and passes a reference to itself as a parameter. (This is sometimes referred to as registration.  That is to say, one object registers itself on another object.)

The method in the second object saves the reference that it receives as an incoming parameter.  This makes it possible for a method in the second object to make a callback to the first object sometime later.  This is illustrated in the program named This03, shown in Listing 3.
 

/*File This03.java 
Copyright 2002, R.G.Baldwin
Illustrates using the this keyword in
a callback scenario.

Tested using JDK 1.4.0 under Win2000

The output from this program is:

Instance variable myVar = 15
**************************************/

class This03 {
  public static void main(
                        String[] args){
    ClassA objA = new ClassA();
    ClassB objB = new ClassB();
    objA.goRegister(objB);
    objB.callHimBack();
    objA.showData(); 
  }//end main method
}//End This03 class definition.
//===================================//
  
class ClassA{
  int myVar;
  
  void goRegister(ClassB refToObj){
    refToObj.registerMe(this);

  }//end goRegister
  //---------------------------------//
  
  void callMeBack(int var){
    myVar = var;
  }//end callMeBack
  //---------------------------------//
  
  void showData(){
    System.out.println(
           "Instance variable myVar = "
                              + myVar);
  }//end showData
}//end ClassA
//===================================//

class ClassB{
  ClassA ref;
  
  void registerMe(ClassA var){
    ref = var;
  }//end registerMe
  //---------------------------------//
  
  void callHimBack(){
    ref.callMeBack(15);
  }//end callHimBack
  
}//End ClassB class definition

Listing 3

Not intended to be useful

Note that the program in Listing 3 is intended solely to illustrate the concept of a callback, and is not intended to do anything useful.  This is a rather long and convoluted explanation, so please bear with me.

The main method begins by instantiating two objects, one each from the classes named ClassA and ClassB.

Go register yourself

Then the main method sends a message to objA telling it to go register itself on objB.  A reference to objB is passed as a parameter to the method named goRegister belonging to objA.

The code in objA uses this reference to invoke the method named registerMe on objB, passing this as a parameter.  In other words, the code in objA invokes a method belonging to objB passing a reference to itself as a parameter.  The code in objB saves that reference in an instance variable for later use.

Make a callback

Then the main method sends a message to objB asking it to use the saved reference to make a callback to objA.  The code in the method named callHimBack uses the reference to objA saved earlier to invoke the method named callMeBack on objA, passing 15 as a parameter.  The method named callMeBack belonging to objA saves that value in an instance variable.

Show the data

Finally, the main method invokes the showData method on objA to cause the value stored in the instance variable belonging to objA to be displayed on the computer screen.

Callbacks are important

Again, this program is provided solely to illustrate the concept of a callback using the this keyword.  In practice, callbacks are used throughout Java, but they are implemented in a somewhat more elegant way, making use of interfaces.

For example, interfaces with names like Observer and MouseListener are commonly used to register observer objects on observable objects (sometimes referred to as listeners and sources).  Then later in the program, when something of interest happens on the observable object (the source), all registered observer objects (the listeners), are notified of the event.

The main point regarding the this reference

The main point of this discussion is that the this reference is available to all instance methods belonging to an object, and can be used whenever there is a need for a reference to the object on which the method is invoked.

To disambiguate something

At least one prominent author uses the word disambiguate to describe the process discussed above, where the this keyword is used to bypass one variable in favor of a different variable having the same name.  I will also use that terminology in the following discussion.

Three uses of the super keyword

If your class overrides a method in a superclass, you can use the super keyword to bypass the overridden version in the class and execute the version in the superclass.

If a local variable in your method or a member variable in your class hides a member variable in the superclass (having the same name), you can use the super keyword to access the member variable in the superclass.

You can also use super in a constructor of your class to invoke a parameterized constructor in the superclass.

The program named Super3

The program in Listing 4 uses super to invoke a parameterized constructor in the superclass from the subclass constructor.  This is an important use of super.

The program also uses this and super to disambiguate a local variable, an instance variable of the subclass, and an instance variable of the superclass.  All three variables have the same name.
 

/*File Super3.java 
Copyright 2002, R.G.Baldwin
Illustrates use of super reference to 
access constructor in superclass.  Also
illustrates use of super to 
disambiguate instance variable in 
subclass from instance variable in 
superclass.  Illustrates use of this
to disambiguate local variable from
instance variable in subclass.

Tested using JDK 1.4.0 under Win2000

The output from this program is:

In SuperClass constructor.
Setting superclass instance var to 500

In subclass constructor.
Setting subclass instance var to 400

In main
Subclass instance var = 400

In method myMeth
Local var = 300
Subclass instance var = 400
SuperClass instance var = 500
**************************************/
class SuperClass{
  int data;

  //Parameterized superclass 
  // constructor
  public SuperClass(int val){
    System.out.println(
        "In SuperClass constructor. ");
    System.out.println(
         "Setting superclass instance "
                   + "var to " + val);
    data = val;
    System.out.println();//blank line
  }//end SuperClass constructor
}//end SuperClass class definition
//===================================//

class Super3 extends SuperClass{
  //Instance var in subclass has same
  // name as instance var in superclass
  int data;

  //Subclass constructor
  public Super3(){
    //Call parameterized SuperClass 
    // constructor
    super(500);
    System.out.println(
           "In subclass constructor.");
    System.out.println(
       "Setting subclass instance var "
                           + "to 400");
    data = 400;
    System.out.println();//blank line
  }//end subclass constructor
  //---------------------------------//

  //Method illustrates use of this and
  // super to disambiguate local 
  // variable, instance variable of
  // subclass, and instance variable 
  // of superclass.  All three 
  // variables have the same name.
  void myMeth(){ 
    int data = 300;//local variable
    System.out.println(
                   "In method myMeth");
    System.out.println("Local var = " 
                               + data);
    System.out.println(
             "Subclass instance var = "
                          + this.data);
    System.out.println(
           "SuperClass instance var = "
                         + super.data);
  }//end method myMeth
  //---------------------------------//

  public static void main(
                       String[] args){
    Super3 obj = new Super3();
    System.out.println("In main");
    System.out.println(
             "Subclass instance var = "
                           + obj.data);
    System.out.println();//blank line
    obj.myMeth();
  }//end main method
}//End Super3 class definition.

Listing 4

The keyword super is used twice in the program in Listing 4 (both cases are highlighted in boldface).

Invoke a parameterized constructor

The first usage of the keyword super appears as the first executable statement in the noarg constructor for the class named Super3.  This statement reads as follows:

super(500);

This statement causes the parameterized constructor for the immediate superclass (the class named SuperClass) of the class named Super3, to be executed before the remaining code in the constructor for Super3 is executed.

This is the mechanism by which you can cause a parameterized constructor in the immediate superclass to be executed.

What if you don't do this?

If you don't do this, an attempt will always be made to invoke a noarg constructor on the superclass before executing the remaining code in the constructor for your class.  (That is why you should almost always make certain that the classes that you define have a noarg constructor in addition to any parameterized constructors that you may define.)

First executable statement in constructor

When super(parameters) is used to invoke the superclass constructor, it must always be the first executable statement in the constructor.

Whenever you invoke the constructor of a class to instantiate an object, if your constructor doesn't have a call to super as the first executable statement in the constructor, the call to the noarg constructor in the superclass is made automatically.

In other words, in order to construct an object of a class, it is necessary to first construct that part of the object attributable to the superclass. That normally happens automatically, making use of the superclass constructor that doesn't take any parameters.

Invoking a parameterized constructor

If you want to use a version of the superclass constructor that takes parameters, you can make your own call to super(parameters) as the first executable statement in your constructor (as was done in this program).

Accessing a superclass member variable

The second use of the super keyword in the program shown in Listing 4 uses the keyword to bypass an instance variable named data in the class named Super3, to access and display the value of an instance variable named data in the superclass named SuperClass.

Note that in that same section of code, the this keyword is used to bypass a local variable named data in order to display the value of an instance variable named data in the class named Super3.

Similarly, a statement without the use of either this or super is used to display the value of a local variable named data.

To disambiguate

Therefore, as stated earlier, the program uses this and super to disambiguate a local variable, an instance variable of the subclass, and an instance variable of the superclass, where all three variables have the same name.

Accessing overridden superclass method

As mentioned earlier, if your method overrides a method in its superclass, you can use the keyword super to invoke the overridden version in the superclass, possibly completely bypassing the overridden version in the subclass.

The program named Super4.

This is illustrated by the program in Listing 5. This program contains an overridden version of a superclass method named meth.  The subclass version uses the value of an incoming parameter to decide whether to invoke the superclass version and then to invoke some of its own code, or to execute its own code exclusively.
 

/*File Super4.java 
Copyright 2002, R.G.Baldwin
Illustrates invoking the superclass
version of an overridden method from
code in the subclass version.

Tested using JDK 1.4.0 under Win 2000.

The output from this program is:

In main
Entering overridden method in subclass
Incoming parameter is false
Subclass version only is invoked
Back in or still in subclass version
Goodbye from subclass version

Entering overridden method in subclass
Incoming parameter is true
SuperClass method invoked
Back in or still in subclass version
Goodbye from subclass version

Back in main
**************************************/
class SuperClass{
  //Following method is overridden in
  // the subclass.
  void meth(boolean par){
    System.out.println(
       "Incoming parameter is " + par);
    System.out.println(
          "SuperClass method invoked");
  }//end meth
}//end SuperClass class definition
//===================================//

class Super4 extends SuperClass{
  //Following method overrides method
  // in the superclass
  void meth(boolean par){
    System.out.println(
          "Entering overridden method "
                      + "in subclass");
    //Decide whether to invoke
    // superclass version
    if(par)
      //Invoke superclass version
      super.meth(par);
    else{ 
      //Don't invoke superclass version
      System.out.println(
       "Incoming parameter is " + par);
      System.out.println(
            "Subclass version only is "
                          + "invoked");
    }//end else      
    //Execute some additional code
    System.out.println(
        "Back in or still in subclass "
                          + "version");
    System.out.println(
      "Goodbye from subclass version");
    System.out.println();//blank line

  }//end overridden meth()
  //---------------------------------//

  public static void main(
                        String[] args){
    //instantiate an object of 
    // this type 
    Super4 obj = new Super4();
    System.out.println("In main");
    //Invoke overridden version of 
    // method
    obj.meth(false);
    //Invoke superclass version of 
    // method
    obj.meth(true);
    System.out.println("Back in main");
  }//end main method
}//End Super4 class definition.

Listing 5

Only one statement contains super

The super keyword is used in only one statement in the program in Listing 5.  That statement appears in the subclass version of an overridden method, and is as follows:

super.meth(par);

This statement is inside the body of an if statement.  If the value of par is true, then this statement is executed, causing the superclass version of the method named meth to be executed (passing the value of par as a parameter to the superclass method).  When the method returns, the remaining code in the subclass version of the method is executed.

If the value of par is false, the above statement is bypassed, and the superclass version of the method doesn't get executed.  In this case, only the code in the subclass version is executed.
 

Summary

I have discussed and illustrated the use of the this keyword in the following common situations:
  • To bypass local variables or parameters that hide member variables having the same name, in order to access the member variable.
  • To make it possible for one overloaded constructor to invoke another overloaded constructor in the same class.
  • To pass a reference to the current object to a method belonging to a different object (as in implementing callbacks, for example).
I have also discussed and illustrated the use of the super keyword in the following situations:
 
  • To bypass the overridden version of a method in a subclass and execute the version in the superclass.
  • To bypass a member variable in a subclass in order to access a member variable having the same name in a superclass.
  • To cause a constructor in a subclass to invoke a parameterized constructor in the immediate superclass.

What's Next?

The next lesson in this miniseries will teach you how to use exception handling in Java.


Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com

-end-
 




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel