Chapter 3
IN THIS CHAPTER
Adding static fields to a class
Creating static methods
Creating classes that can be instantiated
Working with static initializers
Astatic method is a method that isn’t associated with an instance of a class. (Unless you jumped straight to this chapter, you already knew that.) Instead, the method belongs to the class itself. As a result, you can call the method without first creating a class instance. In this chapter, you find out everything you need to know about creating and using static fields and methods.
According to my handy Webster’s dictionary, the word static has several meanings, most of which relate to the idea of being stationary or unchanging. A static display is a display that doesn’t move. Static electricity is an electrical charge that doesn’t flow. A static design is a design that doesn’t change.
As used by Java, however, the term static doesn’t mean unchanging. You can create a static field, for example, and then assign values to it as a program executes. Thus, the value of the static field can change.
To confuse things further, the word static can also mean interference, as in radio static that prevents you from hearing music clearly on the radio. But in Java, the term static doesn’t have anything to do with interference or bad reception.
So what does the term static mean in Java? It’s used to describe a special type of field or method that isn’t associated with a particular instance of a class. Instead, static fields and methods are associated with the class itself, which means that you don’t have to create an instance of the class to access a static field or methods. Instead, you access a static field or method by specifying the class name, not a variable that references an object.
Static fields and methods have many common uses. Here are but a few:
Billing
class might have a constant named
SALES_TAX_RATE
that provides the state sales tax rate.Ball
class used in a game might have a static field that counts how many balls currently exist. This count doesn’t belong to any one instance of the
Ball
class.Invoice
class might maintain a static field that holds the invoice number that is assigned to the next
Invoice
object created from the class.NumberFormat
class, which has static methods such as
getCurrencyInstance
and
getNumberInstance
that return object instances to format numbers in specific ways. One reason you might want to use this technique is to create classes that can have only one object instance. This type of class, called a singleton class
, is described in the sidebar “The Singleton pattern
,” later in this chapter.Math
class, which provides a bunch of static methods to do math calculations. Examples that you might code yourself are a
DataValidation
class with static methods that validate input data and a database class with static methods that perform database operations.A static field
is a field that’s declared with the
static
keyword, like this:
private static int ballCount;
Note that the position of the
static
keyword is interchangeable with the positions of the visibility keywords
(
private
and
public
, as well as
protected
, which I describe in the next chapter). As a result, the following statement works as well:
static private int ballCount;
As a convention, most programmers tend to put the visibility keyword first.
private void someMethod()
{
static int x;
}
In other words, fields can be static, but local variables can’t.
You can provide an initial value for a static field. Here’s an example:
private static String district = "Northwest";
Static fields are created and initialized when the class is first loaded. That happens when a static member of the class is referred to or when an instance of the class is created, whichever comes first.
Another way to initialize a static field is to use a static initializer, which I cover later in this chapter, in the section “Using Static Initializers .”
A static method
is a method declared with the
static
keyword. Like static fields, static methods are associated with the class itself, not with any particular object created from the class. As a result, you don’t have to create an object from a class before you can use static methods defined by the class.
The best-known static method is
main
, which is called by the Java runtime to start an application. The
main
method must be static — which means that applications are run in a static context by default.
One of the basic rules of working with static methods is that you can’t access a nonstatic method or field from a static method, because the static method doesn’t have an instance of the class to use to reference instance methods or fields. The following code won’t compile:
public class TestClass
{
private int x = 5; // an instance field
public static void main(String[] args)
{
int y = x; // error: won't compile
}
}
Here the
main
method is static, so it can’t access the instance variable
x
.
Note: You can access static methods and fields from an instance method, however. The following code works fine:
public class Invoice
{
private static double taxRate = 0.75;
private double salesTotal;
public double getTax()
{
return salesTotal * taxRate;
}
}
Here the instance method named
salesTotal
has no trouble accessing the static field
taxRate
.
One common use for static variables is to keep track of how many instances of a class have been created. To illustrate how you can do this, consider the program
in Listing 3-1
. This program includes two classes. The
CountTest
class is a simple class that keeps track of how many times its constructor has been called. Then the
CountTestApp
class uses a
for
loop to create 10 instances of the class, displaying the number of instances that have been created after it creates each instance.
Note that the instance count in this application is reset to zero each time the application is run. As a result, it doesn’t keep track of how many instances of the
CountTest
class have ever been created — only of how many have been created during a particular execution
of the program.
LISTING 3-1 The CountTest Application
public class CountTestApp →1
{
public static void main(String[] args)
{
printCount();
for (int i = 0; i < 10; i++)
{
CountTest c1 = new CountTest(); →8
printCount(); →9
}
}
private static void printCount()
{
System.out.println("There are now " →15
+ CountTest.getInstanceCount()
+ " instances of the CountTest class.");
}
}
class CountTest →21
{
private static int instanceCount = 0; →23
public CountTest() →25
{
instanceCount++;
}
public static int getInstanceCount() →29
{
return instanceCount;
}
}
The following paragraphs describe some of the highlights of this program:
CountTestApp
class, which tests the
CountTest
class.CountTest
class. Because this code is contained in a
for
loop, 10 instances are created.CountTest
objects have been created so far. It calls the static
getInstanceCount
method of the
CountTest
class to get the instance count.CountTest
class.instanceCount
variable stores the instance count.CountTest
class. Notice that the
instanceCount
variable is incremented within the constructor. That way, each time a new instance of the class is created, the instance count is incremented.getInstanceCount
method simply returns the value of the static
instanceCount
field.Sometimes you want to create a class that can’t be instantiated at all. Such a class consists entirely of static fields and methods. A good example in the Java API is the
Math
class. Its methods provide utility-type functions that aren’t really associated with a particular object. You may need to create similar classes yourself occasionally. You might create a class with static methods for validating input data, for example, or a database access class that has static methods to retrieve data from a database. You don’t need to create instances of either of these classes.
You can use a simple trick to prevent anyone from instantiating a class. To create a class instance, you have to have at least one public constructor. If you don’t provide a constructor in your class, Java automatically inserts a default constructor, which happens to be public.
All you have to do to prevent a class instance from being created, then, is provide a single private constructor, like this:
public class Validation
{
private Validation() {} // prevents instances
// static methods and fields go here
}
Now, because the constructor is private, the class can’t be instantiated.
public final class Math {
/**
* Don't let anyone instantiate this class.
*/
private Math() {}
I figure that if this trick is good enough for the folks who wrote the
Math
class, it’s good enough for me.
In the preceding chapter, you discover initializer blocks that you can use to initialize instance variables. Initializer blocks aren’t executed until an instance of a class is created, so you can’t count on them to initialize static fields. After all, you might access a static field before you create an instance of a class.
Java provides a feature called a static initializer that’s designed specifically to let you initialize static fields. The general form of a static initializer looks like this:
static
{
statements…
}
As you can see, a static initializer is similar to an initializer block but begins with the word
static
. As with an initializer block, you code static initializers in the class body but outside any other block, such as the body of a method or constructor.
The first time you access a static member such as a static field or a static method, any static initializers in the class are executed — provided that you haven’t already created an instance of the class. That’s because the static initializers are also executed the first time you create an instance. In that case, the static initializers are executed before the constructor is executed.
Here’s an example of a class that contains a static initializer:
class StaticInit
{
public static int x;
static
{
x = 32;
}
// other class members such as constructors and
// methods go here…
}
This example is pretty trivial. In fact, you can achieve the same effect just by assigning the value
32
to the variable when it is declared. If, however, you had to perform a complicated calculation to determine the value of
x
— or if its value comes from a database — a static initializer could be very useful.