Tuesday, April 3, 2012

Static or nonstatic?



Many students who lack exposure to object oriented programming concepts are initially confused about the difference between static and nonstatic data members (aka instance variables) and methods of a Java class. Here is my attempt to help these students grasp this elementary concept quickly, without a lot of OO mumbo-jumbo.

Nonstatic.

In C, and in most other languages that have data structures, we can declare a data structure myStructure, containing one or more elements, and a function myFunctionwhich takes a pointer or reference to myStructure as an argument. So myFunctionalways operates on an instance of myStructure. Further, we decree that the argument must not ever be null, i.e. we must always have an instance of myStructure before we can call myFunction. So if p is a pointer to myStructure, we would call myFunction(p).
In the foregoing example, the definition of myFunction is tightly bound to that ofmyStructure. In an OO language such as C++ or Java, this idea is refined and enforced by syntactic rules. Instead of a structure, we can declare a class, let's call it MyClass. Nonstatic data members of a class are similar to the elements of a data structure, in that each instance of a class contains a full copy of the nonstatic data members.
Instead of a function, we can declare a method myMethod, which belongs to the class, so that it can be referred to by its qualified name, MyClass.myMethod in Java orMyClass::myMethod in C++.
Now here's the thing: If myMethod is not declared static, then it implicitly takes an argument which is a reference to an instance of MyClass. The argument doesn't appear in the method's argument list. Inside the method, the argument is always called "this"; and references to data members of MyClass are implicitly qualified by the value of "this" (the context known as "object scope").
In Java, when writing a call to a nonstatic method, you place the reference to MyClass(which becomes "this" inside the method) before the method. So, if r is a reference to an instance of MyClass, then we would call r.myMethod(). This is very much like callingmyFunction(p) in the first example, except for all the syntactic niceties that enforce the calling rules and create object scope.
This behavior is just part of the OO principle called "encapsulation", wherein a group of data values is bundled up and associated with a set of behaviors. There is more to the principle than this, but my goal at the moment is to explain not the principle but the mechanism.
  class MyClass {
    int numberOfToesPerFoot;
    int numberOfFeet;

    // constructor initializes each instance of MyClass
    MyClass(int ntoes, int nfeet)
      numberOfToesPerFoot = ntoes;
      numberOfFeet = nfeet;
    }

    void myMethod() {
      System.out.println("I have " +
                          this.numberOfToesPerFoot * this.numberOfFeet +
                          " toes.");  // "this." could be omitted
                                      // with the same result in this context
    }

    public static void main(String argv[]) {
      MyClass r = new MyClass(5, 2); // must create an instance of MyClass
      r.myMethod();  // invoke myMethod on instance r
    }

Static.

In most respects except for naming, a static data member in Java behaves like a global variable in other languages. There's only one instance of it in the whole environment of the program.
A static method in Java is just a function without any implicit arguments. It doesn't have "this" or "object scope"; you can call it without being in possession of an object of the class to which the method belongs.
When referring to a static method or data member, you can explicitly qualify it by prepending the class name, as in the example below.
  class MyClass {
    static int numberOfToesPerFoot;  // global value for the class MyClass
    static int numberOfFeet;

    static void initializeStatics(int ntoes, int nfeet) {
      numberOfToesPerFoot = ntoes;
      numberOfFeet = nfeet;
    }
      
    static void myStaticMethod() {
      System.out.println("I have " +
                         MyClass.numberOfToesPerFoot * MyClass.numberOfFeet +
                         " toes.");  // "MyClass." could be omitted
                                      // with the same result
    }

    public static void main(String argv[]) {
      initializeStatics(5, 2);   // set the static values
      MyClass.myStaticMethod();  // "MyClass." could be omitted
                                 // in this context
    }
  }

0 comments: