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 (§12.4).
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.
class Point { int x, y, useCount; Point(int x, int y) { this.x = x; this.y = y; } final static 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; p.useCount++; p.origin.useCount++; System.out.println("(" + q.x + "," + q.y + ")"); System.out.println(q.useCount); System.out.println(q.origin == Point.origin); System.out.println(q.origin.useCount); } }
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 Point.origin
, and using variables of the class type in field access expressions (§15.10), as in p.origin
and q.origin
. 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 (§15.20.3):
q.origin==Point.origin
is true
. Further evidence is that the incrementation:
p.origin.useCount++;
causes the value of q.origin.useCount to be 1
; this is so because p.origin
and q.origin
refer to the same variable.
static
FieldsIf a field that is not declared private
was not declared static
and is changed to be declared static
, or vice versa, then a linkage time error, specifically an IncompatibleClassChangeError
, will result if the field is used by a preexisting binary which expected a field of the other kind. Such changes are not recommended in code that has been widely distributed.
A method that is declared static
is called a class method. A class method is always invoked without reference to a particular object. An attempt to reference the current object using the keyword this
or the keyword super
in the body of a class method results in a compile time error. It is a compile-time error for a static
method to be declared abstract
.
A method that is not declared static
is called an instance method, and sometimes called a non-static
method). An instance method is always invoked with respect to an object, which becomes the current object to which the keywords this
and super
refer during execution of the method body.
static
MethodsIf a method that is not declared private
was declared static
(that is, a class method) and is changed to not be declared static
(that is, to an instance method), or vice versa, then compatibility with pre-existing binaries may be broken, resulting in a linkage time error, namely an IncompatibleClassChangeError
, if these methods are used by the pre-existing binaries. Such changes are not recommended in code that has been widely distributed.
Any static initializers declared in a class are executed when the class is initialized and, together with any field initializers, may be used to initialize the class variables of the class.
StaticInitializer:
static
Block
It is a compile-time error for a static initializer to be able to complete abruptly (§14.1, §15.5) with a checked exception (§11.2).
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 catch, at compile time, circular or otherwise malformed initializations. Thus, both:
class Z { static int i = j + 2; static int j = 4; }
and:
class Z { static { i = j + 2; } static int i, j; static { j = 4; } }
result in compile-time errors.
Accesses to class variables by methods are not checked in this way, so:
class Z { static int peek() { return j; }
static int i = peek(); static int j = 1; }
class Test { public static void main(String[] args) { System.out.println(Z.i); }
}
produces the output:
0
because the variable initializer for i
uses the class method peek
to access the value of the variable j
before j
has been initialized by its variable initializer, at which point it still has its default value (§4.5.4).
If a return
statement (§14.15) appears anywhere within a static initializer, then a compile-time error occurs.
If the keyword this
(§15.7.2) or the keyword super
(§15.10, §15.11) appears anywhere within a static initializer, then a compile-time error occurs.
Adding, deleting, or changing a static initializer (§8.5) of a class does not impact pre-existing binaries.