Chapter 3

Working with Statics

IN THIS CHAPTER

check Adding static fields to a class

check Creating static methods

check Creating classes that can be instantiated

check 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.

Understanding 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.

remember The value of a static field is the same across all instances of the class. In other words, if a class has a static field named CompanyName , all objects created from the class will have the same value for CompanyName .

Static fields and methods have many common uses. Here are but a few:

Working with Static Fields

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.

tip Note that you can’t use the static keyword within a class method. Thus the following code won’t compile:

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 .”

Using Static Methods

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 .

Counting Instances

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:

  1. 1 This line is the start of the CountTestApp class, which tests the CountTest class.
  2. 8 This line creates an instance of the CountTest class. Because this code is contained in a for loop, 10 instances are created.
  3. 9 This line calls the printCount method, which prints the number of CountTest objects that have been created so far.
  4. 15 This line prints a message indicating how many CountTest objects have been created so far. It calls the static getInstanceCount method of the CountTest class to get the instance count.
  5. 21 This line is the start of the CountTest class.
  6. 23 The static instanceCount variable stores the instance count.
  7. 25 This line is the constructor for the 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.
  8. 29 The static getInstanceCount method simply returns the value of the static instanceCount field.

Preventing Instances

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.

technicalstuff Incidentally, the Math class uses this technique to prevent you from creating instances from it. Here’s an actual snippet of code from the Math class:

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.

Using Static Initializers

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.

tip If a class has more than one static initializer, the initializers are executed in the order in which they appear in the program.

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.