James Van Boxtel
James Van Boxtel

Reputation: 2405

Best Practice: Java static non final variables

In Java, when should static non final variables be used?

For example

private static int MY_VAR = 0;

Obviously we are not talking about constants here.

public static final int MY_CONSTANT = 1;

In my experience I have often justified them when using a singleton, but then I end up needing to have more than one instance and cause myself great headache and re-factoring.

It seems it is rare that they should be used in practice. What do you think?

Upvotes: 27

Views: 18253

Answers (8)

CasseroleBoi
CasseroleBoi

Reputation: 106

Non-final static variables should be avoided. First of all, these are the closest thing Java has to global variables, and they are known to be bad for various reasons. There can be arguments for them in lower-level languages without classes like C, but they have nothing in favor of them in Java.

First of all, if they can be set from outside of the package, their value can never be relied on because their any future use could change that value. However, even if they can only be mutated from within the package/class, and they were made safe for threading using atomicity, they would still remain unmaintainable in the long run. For example, static fields cannot be injected in a simple manner, which can be useful in both development and testing.

Java provides a superior design pattern - factories. The following code:

class X {
  private static int instanceCount = 0;
  public X(){
    instanceCount++;
  }
  public static getInstanceCount(){
    return instanceCount;
  }
}

can be replaced with

class XFactory {
  private int instanceCount = 0;
  public X newX(){
    instanceCount++;
    return new X();
  }
  public static int getInstanceCount(){
    return instanceCount;
  }
}

That way, for every test or environment, a new factory can be created which does not influence other factories' instance counts - if this count (or anything more complex) ever needed testing, it would not be possible to do with static fields.

Mutable final static fields are, as Tom Hawtin mentioned, pretty much the same as non-final static fields (with the benefit of concurrency), therefore they are also prone to the issues listed above. Classes almost always have a greater scope than instances, so having any class static property be mutable leads to greater coupling, as two things across the whole package/project can depend on the same variable. While having some advantages in very small projects and in debugging, they should be avoided in production because the issues described quickly outweigh the scarce benefits as the project grows.

Upvotes: 0

Daniel Sokolowski
Daniel Sokolowski

Reputation: 12448

Personally for class non-final variables I use the CamelCase notation. It is clear from code that it is a class variable since you have to reference it as such: FooBar.bDoNotRunTests.

On that note, I prefix class instance variables with the this to distinguish them from local scope variables. ex. this.bDoNotRunTests.

Upvotes: 0

Cjxcz Odjcayrwl
Cjxcz Odjcayrwl

Reputation: 22847

Static variables can be used to control application-level behaviour, for example specifying global logging level, server to connect with.

I've met such use cases in old appliations, usually coming from other companies.

Nowadays using static variables for such purposes is obviously bad practice, but it wasn't so obvious in, say, 1999. No Spring, no log4j, no Clean code from R.C.Martin etc.

Java language is quite old now, and even if some feature is strongly discouraged now, it was often used in the beginnings. And because of backward compatibility it's unlikely to change.

Upvotes: 1

uriDium
uriDium

Reputation: 13420

A static variable means that it is available to the class as a whole so both examples are available to the class as a whole. Final means that the value cannot be changed. So I guess the question is when do you want to a value to be available to an entire class and it cannot be changed after it has been instantiated. My guess would be a constant available to all instantiations of that class. Otherwise if you need something like a population counter then the non-final variable.

Upvotes: 0

Uri
Uri

Reputation: 89729

I think wrapping your statics and providing access via singletons (or at a minimum via static methods) is generally a good idea, since you can better control access and avoid some race condition and synchronization issues.

Upvotes: 0

Chris B.
Chris B.

Reputation: 2560

In my experience static non-final variables should only be used for singleton instances. Everything else can be either more cleanly contained by a singleton (such as a cache), or made final (such as a logger reference). However I don't believe in hard and fast rules, so I would take my advice with a grain of salt. That said I would suggest carefully examining any case where you consider declaring a non-final static variable aside from a singleton instance and see if it can be refactored or implemented differently -- i.e. moved into a singleton container or use a final reference to a mutable object.

Upvotes: 1

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147124

When used as a cache, logging, statistics or a debug switch are the obvious reasonable uses. All private, of course.

If you have mutable object assigned to a final field, that is morally the same as having a mutable field.

Some languages, such as Fan, completely disallow mutable statics (or equivalent).

Upvotes: 6

Jon Skeet
Jon Skeet

Reputation: 1499770

Statistics-gathering might use non-final variables, e.g. to count the number of instances created. On the other hand, for that sort of situation you probably want to use AtomicLong etc anyway, at which point it can be final. Alternatively if you're collecting more than one stat, you could end up with a Statistics class and a final reference to an instance of it.

It's certainly pretty rare to have (justifiably) non-final static variables.

Upvotes: 23

Related Questions