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
Are usually constants but can be variables.
Do not require an object in order to be used. They can be referenced by their class name. For example, you can access the constant Math.PI without instantiating a Math object (which is good, because the Math class isn't instantiable).
Only occur once in memory. If declared within an instantiable class, only one incarnation of a static field will exist that is automatically shared by all instances of the class.
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.
Are automatically initialized by the JVM when the class is first loaded into memory. Unless otherwise specified, boolean variables will be false, numeric variables will be zero, char variables will be '\u0000', and object references will be null. 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;
}will display
Part number: 0
Description: nullwhen 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
Can be initialized with a "static initializer". The general syntax is as follows:
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
Do not require an object in order to be called. They can be referenced by their class name. For example, you have called my Keyboard.readInt() method without instantiating a Keyboard object.
Can only access other static features of their class. For example, consider this program
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
An instance method is associated with both a class and an object. It can access the the static features of its class as well as the instance features of its object.
A static method is associated with a class but not an object. It can access the the static features of its class but requires an object in order to access that object's instance features.
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
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
10public 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);
}
}
a
b
c
d
e
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
11public 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));
}
}
Compilation will fail at line 3
Compilation will fail at line 5
Compilation will fail at line 6
Compilation is successful but a runtime error will occur
Compiles and runs to display "Value is 36"
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
17public 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++;
}
}
Compilation will fail at line 3
Compilation will fail at line 15
The program will compile but a runtime exception will occur
The program will compile and run to display "Result: 4"
The program will compile and run to display "Result: 3"
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
18public 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;
}
}
Compilation will fail at line 3
Compilation will fail at line 15
Compilation is successful but a runtime error will occur
Compiles and runs to display
x: 6
y: 2
Compiles and runs to display
x: 3
y: 2