Wednesday, December 10, 2008

Java beginners: beware the black hole of "static"

I've just been grading a bunch of programming assignments from college sophomores taking their second term of Java, and I've noticed a dangerous pattern.

Suppose you have a class like this in your project:


class Foo {
private int state = 42;
void doStuff() { System.out.println(state); }
}

The right way to use the doStuff() method is like this:

Foo f = new Foo();
f.doStuff();

But a common mistake is for people to try to access it like this:

Foo.doStuff();

The latter doesn't work, because it's the syntax for referring to a static method: that is, a method that belongs to the class rather than to each particular object in the class.

So, if you make that mistake, Eclipse gives you the option to

change modifier of doStuff() to static?

Don't do it! Run away! That's not the right way to fix it. In most cases, it means you forgot to create a Foo object.

But suppose you take Eclipse's bad advice anyway. Then you get a new error, because now doStuff() can't see the integer state anymore. What does Eclipse offer to do for you? You guessed it:

change modifier of state to static?

If you do that, then your program will seem to work again. But the meaning is very different, and as soon as you try to use multiple instances of this Foo object, your state variable will appear to do crazy things -- because it will be shared between all your Foo's.

So beware of static. If you have a method that refers to variables that aren't either passed in as arguments, or declared inside its brackets (like state, in this example), then it probably shouldn't be static.

As for making data items static, ask yourself this: think of some future modification of this program where you might need to have several different objects made from this class. Do you want them all to have the same value for this variable? If the answer is "no", then using static is bad form, even if it doesn't currently cause a problem.

So do the extra work and eliminate "static" from your Java code if you've added it in "just to make it compile". It'll be tedious to get it to compile again. It might require you passing extra parameters to methods, or creating new object variables. But take the time to figure it out. Learning this will give you the right intuitions, and will save you headaches later on in your programming career.