Reputation: 2405
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
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
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
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
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
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
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
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
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