4.2.3 Modifiers: final and static


A number of modifier keywords can be placed in declarations of methods and variables, and sometimes in declarations of classes, to provide extra information or restriction on the methods or variables. Here we shall only discuss the final and static keywords.

The final Modifier

The final modifier keyword makes that the programmer cannot change the value anymore. The actual meaning depends on whether it is applied to a class, a variable, or a method. We look at these three cases in more detail.

final Classes

A final class cannot have subclasses. An example:
public final class MathConstants {
  ...
}
This skeleton defines a class called MathConstants that is publicly accessible but cannot be subclassed.

final Variables

A final variable cannot be changed once it is initialized, In the above class of mathematical constants you can for example define a numerical approximation of pi by
  public final static double PI = 3.141592654;
It is a convention, but not obligatory, to capitalize the name of a final object.

final Methods

A final method cannot be overridden by subclasses. There are two reasons for introducing such a method:
  1. Disallowing subclasses to change the meaning of the method;
  2. Increasing efficiency by allowing the compiler to turn calls to the method into inline Java code.
In the class of mathematical constants you could define a final method to generate a random constant.
  public final static randomNumber() {
    ...
  }

The static Modifier

A variable or method that is shared by all instances of a class is called a class variable or class method. You recognize such a variable in Java by the static keyword in the declaration. A class variable will instantiate only one copy of the variable for the whole class instead of a separate copy for each instance of a class. A class variable belongs to a class, not to an instance of the class.

You can refer to a class variable either through an instance of the class (like a normal instance variable) or through the full class name of the form classname.variable.

A class method can be referred to through an instance of the class (like a normal method) or through the full class name of the form classname.method. In fact, a class is an object of the special class Class, so this naming system is consistent.

You can look at the examples above for how to use class variables and class methods. You can also look at the example worked out below.

The Geometrical Shapes Example

We shall give an example of the Shape class with the subclasses Circle and Square. In this example you can practice your knowledge of modifiers and access specifiers.
MathConstants.java
A class for mathematical constants that cannot be subclassed and contains the mathematical constant pi.
public final class MathConstants {
  public final static double PI = 3.141592654; // constant pi
}
ShapeCounter.java
A class for counting the number of geometrical objects that cannot be subclassed and does not allow direct access to the variable that holds in fact the number of shapes; instead, accessor methods are provided to classes in the same package to which this class belongs.
public final class ShapesCounter {
  private static int shapesCount = 0; // total number of geometrical objects
  private static final int maxCounter = 1000; // maximum number of objects

  protected static int shapesCount() {
    return shapesCount;
  }
 
  protected static void incrementShapesCount() {
    shapesCount++;
  } 

  protected static void decrementShapesCount() {
    shapesCount--;
  }
}
Shape.java
A class defining common aspects of shapes such as the coordinates of the distinguished point of the shape.
public class Shape {
  protected double x, y;  // position of geometrical object
}
Circle.java
A class for a circular shape with limited radius, a method to rest the maximal size, and methods to compute the area and the circumference of the circle.
public class Circle extends Shape {
  protected double r;  // radius
  private static double maxSize = 100; // maximal radius

  Circle(double x, double y, double r) {
    super.x = x;
    super.y = y;
    this.r = r;
    ShapesCounter.incrementShapesCount();
  }

  public static void setMaxSize(double size) {
    maxSize = size;
  }

  public double area() {
    return MathConstants.PI * r * r;
  }

  public double circumference() {
    return 2 * MathConstants.PI * r;
  }
}
Square.java
A class for a square shape with methods to compute the area and the circumference of the square.
public class Square extends Shape {
  protected double size;  // radius
  private static double maxSize = 100; // maximal size

  Square(double x, double y, double size) {
    super.x = x;
    super.y = y;
    this.size = size;
    ShapesCounter.incrementShapesCount();
  }

  public static void setMaxSize(double size) {
    maxSize = size;
  }

  public double area() {
    return size * size;
  }

  public double circumference() {
    return 4 * size;
  }
}