Module 4: Java objects, Part I: static objects


What is a static object?

Now at last we will understand what the static keyword means.

In-Class Exercise 4.1: Download StaticExample.java and add a second data member (say, another int) to the StaticExample. Then, in main, assign a value to the new variable and print it.

What happens if you leave out the keyword static? E.g., (source file)


public class StaticExample2 {

  static double x;                      // Static data

  static void printx ()                 // Static method
  {
    System.out.println ("x = " + x);
  }

  double y;                             // Non-static data

  void printy ()                        // Non-static method
  {
    System.out.println ("y = " + y);
  }

  public static void main (String[] argv)
  {
    x = 5.34;
    printx ();

    y = 9.67;   // Won't compile
    printy ();  // Won't compile
  }

}

The problem is, both y and printy() are not static and need an object instance to be created (using new) before use.

The following does work (source file):


public class StaticExample3 {

  static double x;                      // Static data

  static void printx ()                 // Static method
  {
    System.out.println ("x = " + x);
  }

  public double y;                      // Non-static data

  public void printy ()                 // Non-static method
  {
    System.out.println ("y = " + y);
  }

  public static void main (String[] argv)
  {
    x = 5.34;
    printx ();

    // Create an instance of the object.
    StaticExample3 z = new StaticExample3 ();

    // Then, use it.
    z.y = 9.67;
    z.printy ();  
  }

}


Note:

  • The above object, StaticExample3.java, is really both static and non-static (dynamic).
  • What is odd is that a class can have both static and non-static components simultaneously.
  • In Java, the static components are called class members.
  • The dynamic components are called instance members.
  • Once we see dynamic objects, we will better understand the strange syntax.


Static objects: inheritance

Consider again the following simple static object (source file):

 
public class StaticExample {

    static double x;                      // Static data
    
    static void printx ()                 // Static method
    {
        System.out.println ("x = " + x);
    }

    public static void main (String[] argv)
    {
        x = 5.34;
        printx ();
    }

}

Java allows the programmer to build on an existing class using inheritance: (source file)


public class StaticExample4 extends StaticExample {

  // A new function
  static void printxNicely ()
  {
    System.out.println ("The value of x is " + x);
  }
  
  public static void main (String[] argv)
  {
    x = 5.34;          // The variable x is inherited.
    printx ();         // This method is inherited.
    printxNicely ();   // This is new.
  }

}

Note:

  • The keyword extends is used to indicate inheritance.
  • The class StaticExample4 derives or inherits from StaticExample.
  • Alternatively, StaticExample4 is a subclass of StaticExample.
    (And
    StaticExample is the superclass or parent class of StaticExample4.
  • The variables and methods are inherited.

Why is inheritance useful?

  • Inheritance allows you to build on existing code without having to copy code over.
  • Modifications made to the parent class pass on to the subclasses.
  • Any number of classes can inherit from one parent.
  • Inheritance allows you to specialize an existing class for a specific purpose.

However, this form of inheritance is of limited use without the ability to override superclass methods and data in the subclass.


Function overriding in subclasses

Instead of adding new data and methods, you can override a parent's methods and data in the subclass.

For example consider StaticExample5.java:


public class StaticExample5 extends StaticExample {

  // A new function that overrides the parent's printx()
  static void printx ()
  {
    System.out.println ("The value of x is " + x);
  }
  
  public static void main (String[] argv)
  {
    x = 5.34;                // The variable x is inherited.
    printx ();               // The printx function in this class.
    StaticExample.printx();  // The parent's function is still accessible.
  }

}

Note:

  • To override a function, use both the same name and same signature.
  • The function overridden is called a shadowed method.
  • You can override data too.
  • You can prevent inheritance by using the keyword final in the class definition, e.g.,
  •          public final class StaticExample {
               // Rest of class not shown
             }
           

As we will see later, function overriding is a key aspect of object-oriented programming.


Visibility

  • Java allows the programmer to define various levels of visibility for a class' members.
  • The keywords used for this purpose are: public, private and protected.
  • There are two visibility levels for classes:
    • public: visible everywhere.
    • (default: no keyword): visible within the package.

  • There are 4 visibility levels for members of a class:
    • public: visible everywhere.
    • private: visible only inside the class (not visible to or inherited by subclasses).
    • protected: visible inside the class, inside subclasses and inside the package.
    • (default: no visibility keyword): visible to all classes in the package.
      (Not visible to subclasses that are not in the package).

Example: (source file)

class A {
             static int w = 1;
  private    static int x = 2;
  public     static int y = 3;
  protected  static int z = 4;

  public static void main (String[] argv)
  {
    System.out.println (" w = " + w);
    System.out.println (" x = " + x); 
    System.out.println (" y = " + y);
    System.out.println (" z = " + z);
  }

}

class B extends A {
  public static void main (String[] argv)
  {
    System.out.println (" w = " + w);
    System.out.println (" x = " + x);  // Compiler error.
    System.out.println (" y = " + y);
    System.out.println (" z = " + z);
  }
}

class C {
  public static void main (String[] argv)
  {
    System.out.println (" w = " + A.w);
    System.out.println (" x = " + A.x); // Compiler error.
    System.out.println (" y = " + A.y);
    System.out.println (" z = " + A.z);
  }
}

In-class exercise 4.2: Write code to test whether the following assertions are true:

  • In a subclass, you can override a parent's protected function.
  • In a subclass, you can override a parent's public function and make itprotected in the subclass.
  • In a subclass, you can override a parent's public function and make it private in the subclass.