Prev Next

The static keyword

So far the attributes and the methods that we dealt with are referred to as instance attributes and instance methods. i.e. they belong to an object or instance of a class. For example, if there are two instances of Point class namely p and q, p.x is different from q.x and p.xProjection() is different from q.xProjection().

1. Static methods

Static methods (as well as static attributes) belong to a class rather than an object. They are invoked using the class name and not the object name. Put it other way, one doesn't have to instantiate an object to call static methods.

An example

Consider a class SomeClass defined as below.

  public class SomeClass {

    public void instanceMethod() { 
        // Does something 
    }

    public static void staticMethod() { // Note the keyword static
        // Does something else
    }
  }

To invoke instanceMethod() you need to instantiate the SomeClass. But staticMethod() can be invoked by the class name.

  SomeClass sc = new SomeClass(); 	// Needs to be instantiated
  sc.instanceMethod();              // to invoke an instance method

  SomeClass.staticMethod();    // Can be invoked by class name

Use of static methods

Any method whose functionality is common to all object instances and is not tied to a specific instance can be declared as a static method.

In the previous section we defined the auxiliary method absolute(). This is a perfect candidate for being declared static. The working of absolute() is not affected by the different instances of Point class. It takes and returns an integer and has nothing to do with the attributes.

  private static int absolute(int num) { // Note the static keyword
    if (num < 0)
      return num * -1;
    else
      return num;
  }

And it can be invoked from distance() as:

  public int distance(Point q) {
    int absx = Point.absolute(q.x - this.x);
    int absy = Point.absolute(q.y - this.y);
    return absx + absy;
  }

Another reason to use static method(s) is to access/modify static attributes. This is discussed next.

Note: A static method cannot modify instance attributes. Technically speaking, the keyword 'this' does not make sense for static method and therefore cannot be used to access instance attibutes or instance methods.

A word of caution

Excessive use of static methods kills the spirit of object oriented programming. That an object has a life of its own, that it moves from one state to the other, that exhibits certain behavior, that it delegates (part of) its work to other objects and that it interacts with other objects of the system to accomplish a larger goal and are the hallmarks of object oriented paradigm.

Bottomline: Use static methods only when necessary.

Here is a bad example of a static method.

 
    public static Point add(Point p, Point q) {
       return new Point(p.x+q.x, p.y+q.y);
    }        

The driver code is as follows.

 
      Point p = new Point(5,8);
      Point q = new Point(2,8);
      Point r = Point.add(p, q); 
      r.print();
  

Why? Because in the case of p.add(q), p collabroates with q by invoking its add feature to compute the sum while in the case of Point.add(p,q), p and q are manipulated by static method add() which is not a feature of p or q in particular.

2. Static attributes

Like static methods, static attributes belong to a class not to any particular object instance. Hence, they are initialized during declaration itself. Static attributes are usually modified by both static and instance methods.

Since static attributes are not instance members, they are shared by all object instances of the class. So basically non-static methods can access these static members.

An example below. The static attribute 'numPoints' is used to count the number of Point instances created so far and hence incremented every time any one of the constructors are invoked. This can be done directly by "numPoints++;" or by calling a static method "increment()". Both are shown.

In addition, we will also add another static method to print the number of Point instances.

public class Point {
  private int x;  // instance attribute
  private int y;  // instance attribute
  private static int numPoints = 0; // static attribute - initialized right here

  Point() { 
      this.x = 0;
      this.x = 0;
      numPoints++;  // Increment whenever a new instance comes into existence
                    // Also, constructor is incrementing the static attribute
  }

  Point(int xInit, int yInit) {
    this.x = xInit;
    this.y = yInit;
    increment();   // Can also call a static method to increment
  }

  private static void increment() { // Why private?
    numPoints++;
  }

  public static void printCount() {
    System.out.println("Number of Point instances = " + numPoints);
  }
}

The driver code as follows.

      Point.printCount();   // Should print 0
      Point p = new Point(2,3);
      Point.printCount();   // Should print 1
      Point q = new Point();
      Point.printCount();   // Should print 2

A few important points to note

1. The static attribute numPoints is initialized during declaration itself. It is technically incorrect to initialize them as part of constructor. Therefore, always initialize static attributes while declaration.

2. The constructors are instance specific but still can access the (common) static attribute numPoints. Instance methods can access static attributes.

3. On the other hand, accessing instance variables x and y from either of the static methods increment() or printCount() are not possible. In fact, even if it wants to, how can it ever know if it is p's x and y or q's x and y? Referring to them as Point.x and Point.y simply doesn't make sense. Static methods cannot access instance attributes.

4. In the same vein, it is incorrect to use 'this' for static attributes. For instance, in the above code, it is incorrect to use this.numPoints or even p.numPoints, as numPoints does not belong to any particular instance of Point. Never use 'this' for static attributes. Never use class name for accessing instance attributes.

5. Since numPoints needs to be incremented only when a constructor is called, it is safer to make increment() as private, to ensure it is not invoked accidently from outside leading to spurious or incorrect value.

The main() method is static

If you notice the main() method it is declared static. In fact, it has to be static since main() is the entry point of the Java program. If JVM has to invoke main() without executing a single line of the program and pass the control to it, it has to both static (and of course public too).

As an exercise, you can (1) try to declare main as non-static or non-public or both and see what happens. (2) Also, try to overload main() method. (3) Can you call the main() method as you invoke others, say Driver.main()? Check it out. Note down your observations.