static and instance features of a class

 

Overview

Until now, all that has been said of the static keyword is that it identifies a class feature (a field or a method) that is associated with a class and not an instance of the class. You have seen it coded in the header of the main() method

public static void main(String[] args)

and in the header of other class methods. You have also seen it used in the declaration of a constant field within an instantiable class such as

public static final double MONTHLY_RATE = .015;

which appeared in the Customer class of the previous lesson.

It is now time that you learn the full significance of the static keyword when it appears in the declaration of a field or a method.

 

static fields

Sharing an immutable constant isn't a problem. Sharing a variable, however, can lead to confusion if the programmer isn't careful about how he or she references the variable. Consider the following program: 

public class App {
  public static void main(String[] args) {
    Number x = new Number();
    Number y = new Number();
    x.theOneAndOnlyNumber = 3;
    y.theOneAndOnlyNumber = 7;
    System.out.println("Value is " + x.theOneAndOnlyNumber);
  }
}
class Number {
  public static int theOneAndOnlyNumber;
}

The Java compiler permits a static feature of an instantiable class to be accessed by either an object reference or the class name. The above sample uses an object reference to access theOneAndOnlyNumber. As a static variable of the Number class, it is shared by the two Number objects (x and y). Any change made by one object will be seen by the other object. When this code is run, "Value is 7" will display.

The following code is even worse:

public class App {
  public static void main(String[] args) {
    Number x = new Number();
    Number y = new Number();
    x.theOneAndOnlyNumber = 3;
    y.theOneAndOnlyNumber = 7;
    System.out.println("Value is " + Number.theOneAndOnlyNumber);
  }
}
class Number {
  public static int theOneAndOnlyNumber;
}

In the above sample, theOneAndOnlyNumber is referenced three different ways! To avoid confusion, always reference a static variable by using its class name. For example,

public class App {
  public static void main(String[] args) {
    Number x = new Number();
    Number y = new Number();
    Number.theOneAndOnlyNumber = 3;
    Number.theOneAndOnlyNumber = 7;
    System.out.println("Value is " + Number.theOneAndOnlyNumber);
  }
}
class Number {
  public static int theOneAndOnlyNumber;
}

Objects x and y are really irrelevant to the setting of theOneAndOnlyNumber because it is associated with the class and not a particular object of the class. The above code makes this clear.

public class App {
  public static void main(String[] args) {
    System.out.println("Part number: " + Part.number);
    System.out.println("Description: " + Part.description);
  }
}
class Part {
  public static int number;
  public static String description;
}

will display

Part number: 0
Description: null

when run because number is automatically initialized to zero and description is a null object reference. If initial values are specified as follows

public class App {
  public static void main(String[] args) {
    System.out.println("Part number: " + Part.number);
    System.out.println("Description: " + Part.description);
  }
}
class Part {
  public static int number = 17;
  public static String description = "Left-handed widget";
}

the program's output will be

Part number: 17
Description: Left-handed widget

static {
  statements
;
}

where statements assign initial values to previously declared static fields within the class. For example,

public class App {
  public static void main(String[] args) {
    System.out.println("Part number: " + Part.number);
    System.out.println("Description: " + Part.description);
  }
}
class Part {
  public static int number;
  public static String description;
 
static {
    number = 4;
    description = "Widget extender";
  }

}

has a static initializer in the Part class that initializes the static class variables. Static initializers are similar constructors but they do not accept parameters, cannot be called, and do not instantiate an object. They are automatically executed when the JVM first loads the class into memory.

 

static (class) methods

public class App {
  String msg = "Hello World!";
  public static void main(String[] args) {
    System.out.println(msg);
  }
}

Note that msg is a non-static, instance variable within the App class that references a string. The main() method, however, is static. Attempting to compile and execute this program will result in a compile error that says

"non-static variable msg cannot be referenced from a static context"

This is a VERY common mistake. One solution is to simply make the variable static as shown by

public class App {
 
static String msg = "Hello World!";
  public static void main(String[] args) {
    System.out.println(msg);
  }
}

Another solution is to construct an App object and use it to reference the instance variable as shown by

public class App {
  String msg = "Hello World!";
  public static void main(String[] args) {
   
App myApp = new App();
    System.out.println(
myApp.msg);
  }
}

This may seem strange at first glance, but Java allows a class to instantiate and use an object of itself. The technique, in fact, is frequently used.

 

Summary of method access

The following table summarizes these points:

Method type How indicated Class features accessible? Instance features accessible?
instance method

static NOT coded in method header

YES

YES

class method

static coded in method header

YES

NO

 

Lab exercise for Ferris students

E-mail your answers to this assignment no later than the due date listed in the class schedule.

 

Review questions

  1. Which variable name can legally be coded in place of the XXXXX in line 8 the following program.  (choose three)

1
2
3
4
5
6
7
8
9
10
public class App {
  static char a = 'a';
  boolean b = true;
  double c =5.2;
  static short d = 33;
  public static void main(String[] args) {
    byte e = 2;
    System.out.println("Value is " + XXXXX);
  }
}
  1. a

  2. b

  3. c

  4. d

  5. e

  1. What will result from attempting to compile and execute the following program? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
11
public class App {
  static int x = 12;
  int y = 24;
  public static void main(String[] args) {
    App myApp = new App();
    myApp.show();
  }
  public void show() {
    System.out.println("Value is " + (x + y));
  }
}
  1. Compilation will fail at line 3

  2. Compilation will fail at line 5

  3. Compilation will fail at line 6

  4. Compilation is successful but a runtime error will occur

  5. Compiles and runs to display "Value is 36"

  1. What will result from attempting to compile and execute the following program? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class App {
  static int z;
  static {
    z = 1;
  }
  public static void main(String[] args) {
    App app1 = new App();
    app1.bump();
    App app2 = new App();
    app2.bump();
    z++;
    System.out.println("Result: " + z);
  }
  public void bump() {
    z++;
  }
}
  1. Compilation will fail at line 3

  2. Compilation will fail at line 15

  3. The program will compile but a runtime exception will occur

  4. The program will compile and run to display "Result: 4"

  5. The program will compile and run to display "Result: 3"

  1. What will result from attempting to compile and execute the following program? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class App {
  public static void main(String[] args) {
    SomeClass aClass = new SomeClass();
    System.out.println("x: " + aClass.x);
    System.out.println("y: " + aClass.y);
  }
}
class SomeClass {
  public static int x;
  public int y;
  static {
    x = 6;
  }
  public SomeClass() {
    x = 3;
    y = 2;
  }
}
  1. Compilation will fail at line 3

  2. Compilation will fail at line 15

  3. Compilation is successful but a runtime error will occur

  4. Compiles and runs to display

x: 6
y: 2

  1. Compiles and runs to display

    x: 3
    y: 2