[Link].
static Fields
If a field is declared static, there exists exactly one incarnation of the field, no matter how many
instances (possibly zero) of the class may eventually be created. A static field, sometimes called a
class variable, is incarnated when the class is initialized.
A field that is not declared static (sometimes called a non-static field) is called an instance
variable. Whenever a new instance of a class is created, a new variable associated with that instance
is created for every instance variable declared in that class or any of its superclasses.
Example [Link]-1. static Fields
class Point {
int x, y, useCount;
Point(int x, int y) { this.x = x; this.y = y; }
static final Point origin = new Point(0, 0);
}
class Test {
public static void main(String[] args) {
Point p = new Point(1,1);
Point q = new Point(2,2);
p.x = 3;
p.y = 3;
[Link]++;
[Link]++;
[Link]("(" + q.x + "," + q.y + ")");
[Link]([Link]);
[Link]([Link] == [Link]);
[Link]([Link]);
}
}
This program prints:
(2,2)
0
true
1
showing that changing the fields x, y, and useCount of p does not affect the fields of q, because these
fields are instance variables in distinct objects. In this example, the class variable origin of the
class Point is referenced both using the class name as a qualifier, in [Link], and using
variables of the class type in field access expressions, as in [Link] and [Link]. These two
ways of accessing the origin class variable access the same object, evidenced by the fact that the
value of the reference equality expression:
[Link]==[Link]
is true. Further evidence is that the incrementation:
[Link]++;
causes the value of [Link] to be 1; this is so because [Link] and [Link] refer
to the same variable.
Example [Link]-2. Hiding of Class Variables
class Point {
static int x = 2;
}
class Test extends Point {
static double x = 4.7;
public static void main(String[] args) {
new Test().printX();
}
void printX() {
[Link](x + " " + super.x);
}
}
This program produces the output:
4.7 2
because the declaration of x in class Test hides the definition of x in class Point, so class Test does
not inherit the field x from its superclass Point. Within the declaration of class Test, the simple
name x refers to the field declared within class Test. Code in class Test may refer to the field x of
class Point as super.x (or, because x is static, as Point.x). If the declaration of Test.x is
deleted:
class Point {
static int x = 2;
}
class Test extends Point {
public static void main(String[] args) {
new Test().printX();
}
void printX() {
[Link](x + " " + super.x);
}
}
then the field x of class Point is no longer hidden within class Test; instead, the simple name x now
refers to the field Point.x. Code in class Test may still refer to that same field as super.x.
Therefore, the output from this variant program is:
2 2
Example [Link]-3. Hiding of Instance Variables
class Point {
int x = 2;
}
class Test extends Point {
double x = 4.7;
void printBoth() {
[Link](x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
[Link]();
[Link](sample.x + " " + ((Point)sample).x);
}
}
This program produces the output:
4.7 2
4.7 2
because the declaration of x in class Test hides the definition of x in class Point, so class Test does
not inherit the field x from its superclass Point. It must be noted, however, that while the field x of
class Point is not inherited by class Test, it is nevertheless implemented by instances of class Test.
In other words, every instance of class Test contains two fields, one of type int and one of
type double. Both fields bear the name x, but within the declaration of class Test, the simple
name x always refers to the field declared within class Test. Code in instance methods of
class Test may refer to the instance variable x of class Point as super.x.
Code that uses a field access expression to access field x will access the field named x in the class
indicated by the type of reference expression. Thus, the expression sample.x accesses
a double value, the instance variable declared in class Test, because the type of the
variable sample is Test, but the expression ((Point)sample).x accesses an int value, the
instance variable declared in class Point, because of the cast to type Point.
If the declaration of x is deleted from class Test, as in the program:
class Point {
static int x = 2;
}
class Test extends Point {
void printBoth() {
[Link](x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
[Link]();
[Link](sample.x + " " + ((Point)sample).x);
}
}
then the field x of class Point is no longer hidden within class Test. Within instance methods in the
declaration of class Test, the simple name x now refers to the field declared within class Point. Code
in class Test may still refer to that same field as super.x. The expression sample.x still refers to
the field x within type Test, but that field is now an inherited field, and so refers to the field x declared
in class Point. The output from this variant program is:
2 2
2 2
12.4. Initialization of Classes and Interfaces
Initialization of a class consists of executing its static initializers and the initializers for static fields
(class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the
interface.
Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the
class are not initialized. Similarly, the superinterfaces of an interface are not initialized before the
interface is initialized.
12.4.1. When Initialization Occurs
A class or interface type T will be initialized immediately before the first occurrence of any one of the
following:
• T is a class and an instance of T is created.
• T is a class and a static method declared by T is invoked.
• A static field declared by T is assigned.
• A static field declared by T is used and the field is not a constant variable
A reference to a static field causes initialization of only the class or interface that actually declares it,
even though it might be referred to through the name of a subclass, a subinterface, or a class that
implements an interface.
A class or interface will not be initialized under any other circumstance.
The intent is that a class or interface type has a set of initializers that put it in a consistent state, and
that this state is the first state that is observed by other classes. The static initializers and class variable
initializers are executed in textual order, and may not refer to class variables declared in the class
whose declarations appear textually after the use, even though these class variables are in scope. This
restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
The fact that initialization code is unrestricted allows examples to be constructed where the value of a
class variable can be observed when it still has its initial default value, before its initializing expression
is evaluated, but such examples are rare in practice. (Such examples can be also constructed for
instance variable initialization) The full power of the Java programming language is available in these
initializers; programmers must exercise some care. This power places an extra burden on code
generators, but this burden would arise in any case because the Java programming language is
concurrent.
Example 12.4.1-1. Superclasses Are Initialized Before Subclasses
class Super {
static { [Link]("Super "); }
}
class One {
static { [Link]("One "); }
}
class Two extends Super {
static { [Link]("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
[Link]((Object)o == (Object)t);
}
}
This program produces the output:
Super Two false
The class One is never initialized, because it is not used actively and therefore is never linked to. The
class Two is initialized only after its superclass Super has been initialized.
Example 12.4.1-2. Only The Class That Declares static Field Is Initialized
class Super {
static int taxi = 1729;
}
class Sub extends Super {
static { [Link]("Sub "); }
}
class Test {
public static void main(String[] args) {
[Link]([Link]);
}
}
This program prints only:
1729
because the class Sub is never initialized; the reference to [Link] is a reference to a field actually
declared in class Super and does not trigger initialization of the class Sub.
Example 12.4.1-3. Interface Initialization Does Not Initialize Superinterfaces
interface I {
int i = 1, ii = [Link]("ii", 2);
}
interface J extends I {
int j = [Link]("j", 3), jj = [Link]("jj", 4);
}
interface K extends J {
int k = [Link]("k", 5);
}
class Test {
public static void main(String[] args) {
[Link](J.i);
[Link](K.j);
}
static int out(String s, int i) {
[Link](s + "=" + i);
return i;
}
}
This program produces the output:
1
j=3
jj=4
3
The reference to J.i is to a field that is a constant variable; therefore, it does not cause I to be
initialized.
The reference to K.j is a reference to a field actually declared in interface J that is not a constant
variable; this causes initialization of the fields of interface J, but not those of its superinterface I, nor
those of interface K.
Despite the fact that the name K is used to refer to field j of interface J, interface K is not initialized.