Why are static variables considered evil?
Asked Answered
T

31

720

I am a Java programmer who is new to the corporate world. Recently I've developed an application using Groovy and Java. All through the code I wrote used quite a good number of statics. I was asked by the senior technical lot to cut down on the number of statics used. I've googled about the same, and I find that many programmers are fairly against using static variables.

I find static variables more convenient to use. And I presume that they are efficient too (please correct me if I am wrong), because if I had to make 10,000 calls to a function within a class, I would be glad to make the method static and use a straightforward Class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, right?

Moreover statics reduce the inter-dependencies on the other parts of the code. They can act as perfect state holders. Adding to this I find that statics are widely implemented in some languages like Smalltalk and Scala. So why is this opposition to statics prevalent among programmers (especially in the world of Java)?

PS: please do correct me if my assumptions about statics are wrong.

Titanate answered 11/8, 2011 at 13:14 Comment(19)
Just for the sake of saying, there are no static variables or methods on Smalltalk or Scala, exactly because static methods and variables are against the OOP principles.Tarantella
At least one statement you make is rather curious: "statics reduce the inter-dependencies on the other parts of the code". In general they tighten the dependencies. The code where the call is made is bound very tightly to the called code. No abstraction between, direct dependency.Isreal
Scala widely uses static variables? Using lots of pure(side effect free) static methods is expected given its partially functional nature. But functional programming wants to minimize mutable state, so scala using many static mutable variables would surprise me.Confiscatory
Static variables are essentially global variables. See hereMadiemadigan
Your second paragraph is about an entirely different subject, namely static methods.Westfall
Functional programming also frowns down upon global state as well. If you ever (and you should) get into FP one day, be prepared to ditch the notion of global state.Wellnigh
In addition to the reasons in posts below, I think one of the reasons we need to avoid static variable is because it's hard to integrate with other system due to its scope. With such a integration, different user sessions, for example in a web application, can modify the static variable simultaneously and result in undesirable consequences.Puryear
possible duplicate of Are global static classes and methods bad?Filide
Are you trying to introduce 10 000 as a big number here?Impenitent
instead of cluttering the memory with 10,000 instances of the class. If your method can be static then that shows it doesn't depend upon state. If it doesn't depend upon state why would you need to create 10000 objects? Why not invoke it 10000 times on same object? Unless you meant invoking it from 10000 different locations in which case you obviously need to refactor your code.Ignorance
@KshitizSharma If your method can be static then that shows it doesn't depend upon state: That assertion is incorrect. Static methods should not retain state, but nothing prevents them from doing so -- using static variables. Instead, the state is transferred from where it belongs (on an instance) to a "dumping ground" of a static class. A further example of how statics tend to lead to bad design, and should be avoided.Dragone
As for 'cluttering the memory' and worrying about efficiency, write good code, not fast code. If it's well-designed and later turns out not to be fast enough, you should be able to redesign it as necessary without too much difficulty- it certainly isn't the case the other way around.Reflexive
"I would be glad to make the method static and use a straightforward class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, right?" Why would you need to create it so many times? look on singelton patterns.Oversleep
I think it is required to never use static variables/methods on distributed processing too. Each machine must have its own instantiated full object to deal with, without creating the impression that a static variable would be updated on all machines.Aboard
@Maurício Linhares : why against OOP principles?Pyrometer
I would be glad to make the method static and use a straightforward Class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, right? You don't need a new instance for each call, you can make the 10,000 calls on the same instance. Or if these calls are from different methods or classes then those instances will get GC'ed at some point after they went out of scope.Spatiotemporal
I guess one reason why static fields are often considered evil, besides the human love for being given absolute "rules" to follow without having to think, is that static fields can be accessed also from instances of their class, potentially causing the misunderstanding that we are accessing different values because they are in different instances, while in reality of course we are accessing the very same value no matter which instance we use to do that.Spatiotemporal
@JavaMan because they are global variablesMonopetalous
dropping your compiled application into notepad, all static variables and function names are exposed;Marine
B
782

Static variables represent global state. That's hard to reason about and hard to test: if I create a new instance of an object, I can reason about its new state within tests. If I use code which is using static variables, it could be in any state - and anything could be modifying it.

I could go on for quite a while, but the bigger concept to think about is that the tighter the scope of something, the easier it is to reason about. We're good at thinking about small things, but it's hard to reason about the state of a million line system if there's no modularity. This applies to all sorts of things, by the way - not just static variables.

Bogtrotter answered 11/8, 2011 at 13:18 Comment(19)
That lately seems to be an argument, whether code testable or not. It's a rather flawed reasoning. The argument should be 'good design', and usually good design is testable. But not the other way around: "I can't test it therefor it must be bad design." Don't get me wrong though, I agree with your post in general.Keyser
@M Platvoet: I would say that given a choice between two otherwise equally valid designs, the testable one is superior. Being testable certainly doesn't equate to being well designed, but I've rarely come across untestable good designs, and I think they're sufficiently rare that I have no problem in making testability a general purpose contributing indicator towards good design.Bogtrotter
Not to forget: If you're in an EJB world, you shouldn't use statics or your app is not really manageable by the app-server.Akerboom
@M Platvoet - Testability affects both maintainability and reliability, and I would consider those major factors in the quality of design. They're not the only factors, surely, but IMHO the cost of any given code is a combination of machine cycles, developer cycles, and user cycles. Testability hits two of those three.Lancastrian
@M Platvoet - Testability also tends to affect reusability, since a decoupled class is generally easier to reuse.Decade
M Platvoet - I don't agree with your first comment here. I think if something can't be tested, then it IS bad design; because if I can't test it, I can't know that it works. Would you buy a car if the salesperson told you "The design of this model prevents it from being tested, so I don't know if it actually runs"? Testability is so crucial for software (as well as cars), that competent design DEMANDS that it be included.Bellyful
static variables make initialization, testing and mocking of objects difficult. If you design for testing, you can't really use statics. For more info, see here: teamflawless.org/2012/…Gershon
This limiting of scope, or lack of, has had the greatest impact on the maintainability of software that I have had the experience of maintaining. Or at least, the greatest impact right after naming variables what they are and naming methods what they do.Clothesbasket
Another important fact - "Statics make you lie about class dependencies". Think about "CLASS_A" which profusely uses static functions of some business logic "CLASS_B", which only contains "public static" member functions. Would you be able to clearly define the dependency of CLASS_A in terms of CLASS_B? NO. You will not be required to define the dependency either through a constructor, setter function or passing as function parameter. A call like CLASS_B.somePublicStaticMethod() would emerge from nowhere and will constraint me from thinking in terms of real world entities in OO fashion.Forgetmenot
Static variables don't represent global state. They represent attributes that describe the whole class and not a particular instance.Rivera
@Jon Skeet, an instance counter could be part of the state of a class, the value of an id could be part of the state of an instance. Neither is global nor local. they describe different things.Rivera
@Andres: It's global in that it's specific to the whole process rather than restricted to one instance. Yes, it's qualified, but that's all. I don't think quibbling about that is being terribly helpful - but feel free to add your own answer, of course...Bogtrotter
@Jon Skeet, just add that static is an OO concept related with a value that corresponds to a class and not a scope concept. I think the "evilness" of static has origin on that confusion.Rivera
@Andres: I don't think there's any confusion here. I'm very well aware of the difference, and I would still describe it as global state... in the absence of any state which is truly globally in scope, the meaning has always been clear in every context I've seen. (And the problems with global state have very little to do with scope, IMO.)Bogtrotter
@Jon Skeet, I'd call global state to what you store on a Singleton or on a ServletContext attribute. OO gives you tools for describing a problem through entities. For describing particular entities you use member variables and for describing the abstraction of an entity (A class) you should use static variables.Rivera
@Andres: Sorry, I found that comment very unclear and hard to read - but I don't think this is going to be productive or appropriate for an SO comment thread. Again, I'd suggest that if you think this answer isn't good enough, write your own.Bogtrotter
@DawoodibnKareem Re 'I think if something can't be tested, then it IS bad design; because if I can't test it, I can't know that it works.' => I'm with you in spirit, but to be pedantic untestable code can still be good design. For example, we can't directly test Java lambdas - they are unnamed chunks of code - but that certainly doesn't mean their use implies bad design. As long as you can test the effects of using a lambda that's good enough.Signification
@M Platvoet static initialization is harder to test regardless of design. If your unit tests run in a JVM instance then you have much less control over initializing the statics afresh each time, or none at all if they are immutable. And you can't parallelize the tests. Much easier to unit test when you can construct the unit yourself and give it mocks and not have it go off and fetch static state from another unit.Precondition
So: good design implies testability. One could say that testability is a part of good design.Ventriloquy
O
307

Its not very object oriented: One reason statics might be considered "evil" by some people is they are contrary the object-oriented paradigm. In particular, it violates the principle that data is encapsulated in objects (that can be extended, information hiding, etc). Statics, in the way you are describing using them, are essentially to use them as a global variable to avoid dealing with issues like scope. However, global variables is one of the defining characteristics of procedural or imperative programming paradigm, not a characteristic of "good" object oriented code. This is not to say the procedural paradigm is bad, but I get the impression your supervisor expects you to be writing "good object oriented code" and you're really wanting to write "good procedural code".

There are many gotchyas in Java when you start using statics that are not always immediately obvious. For example, if you have two copies of your program running in the same VM, will they shre the static variable's value and mess with the state of each other? Or what happens when you extend the class, can you override the static member? Is your VM running out of memory because you have insane numbers of statics and that memory cannot be reclaimed for other needed instance objects?

Object Lifetime: Additionally, statics have a lifetime that matches the entire runtime of the program. This means, even once you're done using your class, the memory from all those static variables cannot be garbage collected. If, for example, instead, you made your variables non-static, and in your main() function you made a single instance of your class, and then asked your class to execute a particular function 10,000 times, once those 10,000 calls were done, and you delete your references to the single instance, all your static variables could be garbage collected and reused.

Prevents certain re-use: Also, static methods cannot be used to implement an interface, so static methods can prevent certain object oriented features from being usable.

Other Options: If efficiency is your primary concern, there might be other better ways to solve the speed problem than considering only the advantage of invocation being usually faster than creation. Consider whether the transient or volatile modifiers are needed anywhere. To preserve the ability to be inlined, a method could be marked as final instead of static. Method parameters and other variables can be marked final to permit certain compiler optimiazations based on assumptions about what can change those variables. An instance object could be reused multiple times rather than creating a new instance each time. There may be compliler optimization switches that should be turned on for the app in general. Perhaps, the design should be set up so that the 10,000 runs can be multi-threaded and take advantage of multi-processor cores. If portablity isn't a concern, maybe a native method would get you better speed than your statics do.

If for some reason you do not want multiple copies of an object, the singleton design pattern, has advantages over static objects, such as thread-safety (presuming your singleton is coded well), permitting lazy-initialization, guaranteeing the object has been properly initialized when it is used, sub-classing, advantages in testing and refactoring your code, not to mention, if at some point you change your mind about only wanting one instance of an object it is MUCH easier to remove the code to prevent duplicate instances than it is to refactor all your static variable code to use instance variables. I've had to do that before, its not fun, and you end up having to edit a lot more classes, which increases your risk of introducing new bugs...so much better to set things up "right" the first time, even if it seems like it has its disadvantages. For me, the re-work required should you decide down the road you need multiple copies of something is probably one of most compelling reasons to use statics as infrequently as possible. And thus I would also disagree with your statement that statics reduce inter-dependencies, I think you will end up with code that is more coupled if you have lots of statics that can be directly accessed, rather than an object that "knows how to do something" on itself.

Outstretch answered 16/8, 2011 at 20:20 Comment(9)
I like your answer, I think it focuses on the right tradeoffs to consider around statics rather than some of the red herrings like concurrency and scope. And +1 for singletons, a better question really might have been when to use static variables/methods vs singletons...Akira
Even though the singleton itself might be thread-safe (e.g. by using synchronized methods), it doesn't mean the calling code is free of race conditions with respect to the singleton state.Hoodwink
Also, statics are not against the OOP paradigm. A lot of OOP fanatics will tell you that the class is an object, and the static method is a method of the class object, rather than it's instances. This phenomenon is less present in Java. Other languages, such as Python allow you to use classes as variables and you can access static methods as methods of that object.Hoodwink
The last line of the third paragraph should read, all your non-static variables, if I'm not mistaken.Ovida
The gotchas are not so puzzling once you learn that a static member is not property of instance but of a class. and the class is supposed to be singleton in the class loader hierarchy. That being said I would use static members rarely, especially using static variables.Mettah
I agree with @Ovida last line of the third paragraph should read, all your non-static variables. if I'm not mistaken too,Functional
Object Lifetime , is one very important point that @jessica mentioned.Whallon
@AndréCaron statics are not against the OOP paradigm ? no it is against OOP. because method cannot overriden if use static, its completely violate Polymorphism(OOP concept).Colier
In Android, Currently, I am passing an integer and with that integer, I am deciding what code to run. Suppose, if I pass 1, I am showing some UI and 2, then another UI and so on. I have around 17 18 such integers. So, can I declare these 17 18 integer as static variable in a singleton class and give them some sensible name depend upon their usage to make the code readable.Ceramic
H
103

Evil is a subjective term.

You don't control statics in terms of creation and destruction. They live at the behest of the program loading and unloading.

Since statics live in one space, all threads wishing to use them must go through access control that you have to manage. This means that programs are more coupled and this change is harder to envisage and manage (like J Skeet says). This leads to problems of isolating change impact and thus affects how testing is managed.

These are the two main issues I have with them.

Hedda answered 11/8, 2011 at 13:19 Comment(0)
G
65

No. Global states are not evil per se. But we have to see your code to see if you used it properly. It is quite possible that a newbie abuses global states; just like he would abuses every language feature.

Global states are absolute necessity. We cannot avoid global states. We cannot avoid reasoning about global states. - If we care to understand our application semantics.

People who try to get rid of global states for the sake of it, inevitably end up with a much more complex system - and the global states are still there, cleverly/idiotically disguised under many layers of indirections; and we still have to reason about global states, after unwrapping all the indirections.

Like the Spring people who lavishly declare global states in xml and think somehow it's superior.

@Jon Skeet if I create a new instance of an object now you have two things to reason about - the state within the object, and the state of the environment hosting the object.

Gustavo answered 11/8, 2011 at 14:19 Comment(2)
"I have two things to reason about". Not if I make my test only dependent on the object state. Which is easier, the less global state I have.Corporeal
Dependency injection has nothing to do with global state or global visibility- even the container itself is not global. Compared to "normal" code, the only extra thing that a container-managed object is visible to is to the container itself. In fact, DI is very commonly used to avoid the Singleton Pattern.Schwab
G
37

If you are using the ‘static’ keyword without the ‘final’ keyword, this should be a signal to carefully consider your design. Even the presence of a ‘final’ is not a free pass, since a mutable static final object can be just as dangerous.

I would estimate somewhere around 85% of the time I see a ‘static’ without a ‘final’, it is WRONG. Often, I will find strange workarounds to mask or hide these problems.

Please don’t create static mutables. Especially Collections. In general, Collections should be initialized when their containing object is initialized and should be designed so that they are reset or forgotten about when their containing object is forgotten.

Using statics can create very subtle bugs which will cause sustaining engineers days of pain. I know, because I’ve both created and hunted these bugs.

If you would like more details, please read on…

Why Not Use Statics?

There are many issues with statics, including writing and executing tests, as well as subtle bugs that are not immediately obvious.

Code that relies on static objects can’t be easily unit tested, and statics can’t be easily mocked (usually).

If you use statics, it is not possible to swap the implementation of the class out in order to test higher level components. For example, imagine a static CustomerDAO that returns Customer objects it loads from the database. Now I have a class CustomerFilter, that needs to access some Customer objects. If CustomerDAO is static, I can’t write a test for CustomerFilter without first initializing my database and populating useful information.

And database population and initialization takes a long time. And in my experience, your DB initialization framework will change over time, meaning data will morph, and tests may break. IE, imagine Customer 1 used to be a VIP, but the DB initialization framework changed, and now Customer 1 is no longer VIP, but your test was hard-coded to load Customer 1…

A better approach is to instantiate a CustomerDAO, and pass it into the CustomerFilter when it is constructed. (An even better approach would be to use Spring or another Inversion of Control framework.

Once you do this, you can quickly mock or stub out an alternate DAO in your CustomerFilterTest, allowing you to have more control over the test,

Without the static DAO, the test will be faster (no db initialization) and more reliable (because it won’t fail when the db initialization code changes). For example, in this case ensuring Customer 1 is and always will be a VIP, as far as the test is concerned.

Executing Tests

Statics cause a real problem when running suites of unit tests together (for example, with your Continuous Integration server). Imagine a static map of network Socket objects that remains open from one test to another. The first test might open a Socket on port 8080, but you forgot to clear out the Map when the test gets torn down. Now when a second test launches, it is likely to crash when it tries to create a new Socket for port 8080, since the port is still occupied. Imagine also that Socket references in your static Collection are not removed, and (with the exception of WeakHashMap) are never eligible to be garbage collected, causing a memory leak.

This is an over-generalized example, but in large systems, this problem happens ALL THE TIME. People don’t think of unit tests starting and stopping their software repeatedly in the same JVM, but it is a good test of your software design, and if you have aspirations towards high availability, it is something you need to be aware of.

These problems often arise with framework objects, for example, your DB access, caching, messaging, and logging layers. If you are using Java EE or some best of breed frameworks, they probably manage a lot of this for you, but if like me you are dealing with a legacy system, you might have a lot of custom frameworks to access these layers.

If the system configuration that applies to these framework components changes between unit tests, and the unit test framework doesn’t tear down and rebuild the components, these changes can’t take effect, and when a test relies on those changes, they will fail.

Even non-framework components are subject to this problem. Imagine a static map called OpenOrders. You write one test that creates a few open orders, and checks to make sure they are all in the right state, then the test ends. Another developer writes a second test which puts the orders it needs into the OpenOrders map, then asserts the number of orders is accurate. Run individually, these tests would both pass, but when run together in a suite, they will fail.

Worse, failure might be based on the order in which the tests were run.

In this case, by avoiding statics, you avoid the risk of persisting data across test instances, ensuring better test reliability.

Subtle Bugs

If you work in high availability environment, or anywhere that threads might be started and stopped, the same concern mentioned above with unit test suites can apply when your code is running on production as well.

When dealing with threads, rather than using a static object to store data, it is better to use an object initialized during the thread’s startup phase. This way, each time the thread is started, a new instance of the object (with a potentially new configuration) is created, and you avoid data from one instance of the thread bleeding through to the next instance.

When a thread dies, a static object doesn’t get reset or garbage collected. Imagine you have a thread called “EmailCustomers”, and when it starts it populates a static String collection with a list of email addresses, then begins emailing each of the addresses. Lets say the thread is interrupted or canceled somehow, so your high availability framework restarts the thread. Then when the thread starts up, it reloads the list of customers. But because the collection is static, it might retain the list of email addresses from the previous collection. Now some customers might get duplicate emails.

An Aside: Static Final

The use of “static final” is effectively the Java equivalent of a C #define, although there are technical implementation differences. A C/C++ #define is swapped out of the code by the pre-processor, before compilation. A Java “static final” will end up memory resident in the JVM's class memory, making it (usually) permanent in ram. In that way, it is more similar to a “static const” variable in C++ than it is to a #define.

Summary

I hope this helps explain a few basic reasons why statics are problematic up. If you are using a modern Java framework like Java EE or Spring, etc, you may not encounter many of these situations, but if you are working with a large body of legacy code, they can become much more frequent.

Gershon answered 24/4, 2012 at 23:15 Comment(3)
A Java “static final” will end up memory resident on the stack? I think static variables are stored in the method area.Porterporterage
@Porterporterage - my answer is 10 years old, but good point - as pointed out here, static variables are stored in class memory: https://mcmap.net/q/25004/-what-is-the-actual-memory-place-for-static-variables/1017787Gershon
My point was that it is allocated in more "permanent" memory, typically outside of the control of the application itself (unless you are using OSGi or other dynamic class loading)Gershon
M
34

There are 2 main problems with static variables:

  • Thread Safety - static resources are by definition not thread-safe
  • Code Implicity - You do not know when a static variables is instantiated and whether or not it will be instantiated before another static variable
Mirabella answered 11/8, 2011 at 13:19 Comment(4)
I don't get the Thread Safety point, i think that nothing is thread safe unless you make it so. This does not seem to be related to static things at all, please correct me if i'm missing something.Highmuckamuck
@Highmuckamuck - While it is true that thread-safety is not an issue exclusive to static variables, because by their definition they are to be called from and by different contexts, they are more prune to themMirabella
@Mirabella I understand what you mean, event if "different contexts" is not necessarely equal to "different threads". But it is true that thread-safety needs often to be taken into account with static resources. You should consider clarifying the sentence.Highmuckamuck
There are valid thread safe uses of static resources, for example. private static final Logger LOG = Logger.getLogger(Foo.class); private static final AtomicInteger x = new AtomicInteger(0); As I understand it, static assignments of resources like this are guaranteed thread-safe by the class loader. The Logger instance is or is not thread-safe independently of where you assign the pointer to it. Keeping state in statics is probably not a good idea, but there is no reason it should not be thread-safe.Anacrusis
C
21

Summarising few basic Advantages & Disadvantages of using Static methods in Java:

Advantages:

  1. Globally accessible i.e. not tied with any particular object instance.
  2. One instance per JVM.
  3. Can be accessed by using class name (No object require).
  4. Contains a single value applicable to all instances.
  5. Load up on JVM startup and dies when JVM shuts down.
  6. They doesn't modify state of Object.

Disadvantages:

  1. Static members are always part of memory whether they are in use or not.
  2. You can not control creation and destruction of static variable. Usefully they have been created at program loading and destroyed when program unload (or when JVM shuts down).
  3. You can make statics thread safe using synchronize but you need some extra efforts.
  4. If one thread change value of a static variable that can possibly break functionality of other threads.
  5. You must know “static“ before using it.
  6. You cannot override static methods.
  7. Serialization doesn't work well with them.
  8. They don't participate in runtime polymorphism.
  9. There is a memory issue (to some extent but not much I guess) if a large number of static variables/methods are used. Because they will not be Garbage Collected until program ends.
  10. Static methods are hard to test too.
Civilization answered 22/9, 2016 at 10:41 Comment(12)
The disadvantages 6, 7, 8 and 10 are the disadvantages of the used languages/frameworks, and not the disadvantages of the static variables in general. The disadvantages 1, 4 and 5 exist also for other solutions, like some singleton pattern provided by some framework. (I did not vote to the answer, because I agree the rest and it is a nice collection.)Sain
@peterh: Disadvantage #7 is fundamental to static fields. If a static field is serialized as part of an object, there's no sensible way to handle a scenario where code attempts to deserialize two instances which have different specified values for that static field.Critta
@Critta how do you serialize a static field “as part of an object”?Arrio
@Holger: Serialization code can record whatever information it deems relevant. If serialization code were to record the value of a static field, and deserialization code were to set the value of that field, then programs which only ever use one such instance of the type could save and restore its state, but would break if code tried to deserialize the type when other instances exist.Critta
@Critta so in that scenario, the static fields are to blame and not the serialization code that decided that static fields were part of an object?Arrio
@Holger: Yes, since such behavior in the serialization/deserialization code would allow it to be used in cases where the object is used as a singleton, or where all instances are consistent with each other, and the alternative would be for the object not to be seralizable at all.Critta
@Holger: The same issues arise with dependencies upon static aspects of system state outside an object. Suppose, for example, that one has a class that requires that all keys in a collection be distinct when using case-insensitive comparisons. In a Turkish locale, a lowercase "I" would be "ı", which is distinct from "i". If the object holding a collection also specifies the locale used in comparisons, the presence of both "I" and "i" in an object associated with a Turkish locale would pose no problem. If, however, code uses the system locale, the best one could hope for...Critta
...would be that code which serializes the collection at least records the locale that was used in its creation. Having the collection refuse deserialization under a non-Turkish locale would be annoying, but having the serialized object indicate the required locale would be better than having an object violate its invariants when loaded in another locale, without having any indication as to why.Critta
@Critta you should decide whether serializing static fields poses a fundamental problem, as you said in your first comment or whether doing so is a legitimate use case as you are saying now. No known serialization framework stores static fields. Of course, you can implement your own serialization mechanism storing static fields but when this blows up, don’t blame the static fields.Arrio
@Holger: The encapsulation of static state within a class will make it impossible to serialize/deserialize the class cleanly, or to serialize/deserialize it using "normal" methods. Custom serialization/deserialization code may be able to to handle a useful range of tasks, despite the limitations imposed by the existence of static state, but the existence of static state will impose limitations that no serialization/deserialization code would be able to overcome.Critta
@Holger: It's possible that a class may use static fields without encapsulating static state. For example, a "list control" which attaches an icon bitmap to every object, and would often use the same displayed bit pattern for many objects, might have a global bitmap containing all of the icons, and store for each object the location within the bitmap of its icon. If serialization code stores the actual bit patterns for each object, and deserialization code adds to the global bitmap any icons whose bit patterns don't yet appear there, the fact that there's one static bitmap...Critta
...wouldn't cause any problems because the actual state being encapsulated would be recorded separately with each item. Even if serializing the class stored the bitmap contents and indices thereunto, that wouldn't need to prevent deserialization if code merged the serialized bitmap with the static one, and remapped all indices appropriately.Critta
I
17

Static variables are generally considered bad because they represent global state and are therefore much more difficult to reason about. In particular, they break the assumptions of object-oriented programming. In object-oriented programming, each object has its own state, represented by instance (non-static) variables. Static variables represent state across instances which can be much more difficult to unit test. This is mainly because it is more difficult to isolate changes to static variables to a single test.

That being said, it is important to make a distinction between regular static variables (generally considered bad), and final static variables (AKA constants; not so bad).

Izanami answered 11/8, 2011 at 13:24 Comment(2)
"Static variables represent state across classes" ... I think you mean "static variables represent state across instances"? +1 for "final static AKA constants, not so bad". Since the value can't change, anything that depends on it at one point in time can't implicitly change its behavior at a later time -- the value is the same.Maes
"Static variables represent state across instances" is a much better way of stating it. I've edited my answer.Izanami
P
15

Since no one* has mentioned it: concurrency. Static variables can surprise you if you have multiple threads reading and writing to the static variable. This is common in web applications (e.g., ASP.NET) and it can cause some rather maddening bugs. For example, if you have a static variable that is updated by a page, and the page is requested by two people at "nearly the same time", one user may get the result expected by the other user, or worse.

statics reduce the inter-dependencies on the other parts of the code. They can act as perfect state holders

I hope you're prepared to use locks and deal with contention.

*Actually, Preet Sangha mentioned it.

Prosperous answered 11/8, 2011 at 21:46 Comment(3)
Instance variables have no thread-safety advantages over statics, they are all unprotected variables. Instead, it all comes down to how you protect the code that accesses those variables.Akira
I didn't quite make that claim, but for the sake of discussion: separation is a form of protection. Thread states are separated; global state is not. An instance variable doesn't need protection unless it's explicitly shared between threads; a static variable is always shared by all threads in the process.Prosperous
I wish thread-static variables were more of a first-class concept, since they can be very useful for safely making information available to a wrapped subroutine call without having to pass that information through every layer of wrapping. For example, if an object had methods to render it to the thread's current graphics context, and there were methods to save/restore the current graphics context, using those could often be cleaner than having to pass the graphics context through every method call.Critta
T
13

if I had to make 10,000 calls to a function within a class, I would be glad to make the method static and use a straightforward class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, Right?

You have to balance the need for encapsulating data into an object with a state, versus the need of simply computing the result of a function on some data.

Moreover statics reduce the inter-dependencies on the other parts of the code.

So does encapsulation. In large applications, statics tend to produce spaghetti code and don't easily allow refactoring or testing.

The other answers also provide good reasons against excessive use of statics.

Teleprinter answered 11/8, 2011 at 13:22 Comment(0)
K
10

In my opinion it's hardly ever about performance, it's about design. I don't consider the use of static methods wrong as apposed of the use of static variables (but I guess you are actually talking about method calls).

It's simply about how to isolate logic and give it a good place. Sometimes that justifies using static methods of which java.lang.Math is a good example. I think when you name most of your classes XxxUtil or Xxxhelper you'd better reconsider your design.

Keyser answered 11/8, 2011 at 13:23 Comment(2)
Pure side effect free static methods are perfectly fine IMO. But global mutable state rarely is and I interpret the OP as talking about global state.Confiscatory
@CodeInChaos totally agree. I find the OP is not entirely clear on the difference between static methods and vars.Keyser
I
9

I have just summarized some of the points made in the answers. If you find anything wrong please feel free to correct it.

Scaling: We have exactly one instance of a static variable per JVM. Suppose we are developing a library management system and we decided to put the name of book a static variable as there is only one per book. But if system grows and we are using multiple JVMs then we dont have a way to figure out which book we are dealing with?

Thread-Safety: Both instance variable and static variable need to be controlled when used in multi threaded environment. But in case of an instance variable it does not need protection unless it is explicitly shared between threads but in case of a static variable it is always shared by all the threads in the process.

Testing: Though testable design does not equal to good design but we will rarely observe a good design that is not testable. As static variables represent global state and it gets very difficult to test them.

Reasoning about state: If I create a new instance of a class then we can reason about the state of this instance but if it is having static variables then it could be in any state. Why? Because it is possible that the static variable has been modified by some different instance as static variable is shared across instances.

Serialization: Serialization also does not work well with them.

Creation and destruction: Creation and destruction of static variables can not be controlled. Usually they are created and destroyed at program loading and unloading time. It means they are bad for memory management and also add up the initialization time at start up.

But what if we really need them?

But sometimes we may have a genuine need of them. If we really feel the need of many static variables that are shared across the application then one option is to make use of Singleton Design pattern which will have all these variables. Or we can create some object which will have these static variable and can be passed around.

Also if the static variable is marked final it becomes a constant and value assigned to it once cannot be changed. It means it will save us from all the problems we face due to its mutability.

Iphlgenia answered 20/5, 2016 at 7:10 Comment(0)
N
7

Static variables most importantly creates problem with security of data (any time changed,anyone can change,direct access without object, etc.)

For further info read this Thanks.

Necking answered 11/8, 2011 at 13:22 Comment(1)
This is a bit misleading. It's not the use of static keyword that causes a security issue. It would be the same if you don't declare a field static but declare it public. I get your point but less experienced developer can get the wrong idea from this answer. It would be better to elaborate on this.Sholokhov
R
7

Seems to me that you're asking about static variables but you also point out static methods in your examples.

Static variables are not evil - they have its adoption as global variables like constants in most cases combined with final modifier, but as it said don't overuse them.

Static methods aka utility method. It isn't generally a bad practice to use them but major concern is that they might obstruct testing.

As a example of great java project that use a lot of statics and do it right way please look at Play! framework. There is also discussion about it in SO.

Static variables/methods combined with static import are also widely used in libraries that facilitate declarative programming in java like: make it easy or Hamcrest. It wouldn't be possible without a lot of static variables and methods.

So static variables (and methods) are good but use them wisely!

Rudd answered 20/8, 2011 at 17:2 Comment(0)
S
6

It might be suggested that in most cases where you use a static variable, you really want to be using the singleton pattern.

The problem with global states is that sometimes what makes sense as global in a simpler context, needs to be a bit more flexible in a practical context, and this is where the singleton pattern becomes useful.

Shank answered 11/8, 2011 at 15:5 Comment(0)
T
5

Yet another reason: fragility.

If you have a class, most people expect to be able to create it and use it at will.

You can document it's not the case, or protect against it (singleton/factory pattern) - but that's extra work, and therefore an additional cost. Even then, in a big company, chances are someone will try at some point to use your class without fully paying attention to all the nice comments or the factory.

If you're using static variables a lot, that will break. Bugs are expensive.

Between a .0001% performance improvement and robustness to change by potentially clueless developers, in a lot of cases robustness is the good choice.

Tatiana answered 11/8, 2011 at 23:42 Comment(0)
L
4

I find static variables more convenient to use. And I presume that they are efficient too (Please correct me if I am wrong) because if I had to make 10,000 calls to a function within a class, I would be glad to make the method static and use a straightforward class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, Right?

I see what you think, but a simple Singleton pattern will do the same without having to instantiate 10 000 objects.

static methods can be used, but only for functions that are related to the object domain and do not need or use internal properties of the object.

ex:

public class WaterContainer {
    private int size;
    private int brand;
    ...etc

    public static int convertToGallon(int liters)...

    public static int convertToLiters(int gallon)...

}
Longboat answered 11/8, 2011 at 13:39 Comment(4)
A classical singleton (i.e. one which is accessed by Class.Instance) is barely better than a static variable. It's slightly more testable, but still much worse than designs where you just happen to create a single instance instead of building your code on the assumption there is only one.Confiscatory
Not sure i understand your comment! i was responding to the OP about what he stated in italic about instancing 10 000 objects. I don't understand why you compare a singleton and a static variable? What i understand from what you wrote is that Singleton is bad design...! I guess i misunderstand you, since the Spring Framework make by default all the beans Singleton ;-)Longboat
A classic singleton(that has Class.Instance) that carries mutable state is bad design IMO. In that case I strongly prefer a design where I get the singletons I need to use passed as parameter into the class that uses them (typically with the help of DI). Logically immutable classic singletons are fine IMO.Confiscatory
@Longboat In case it wasn't clear why a Class singleton (a singleton where the class ensure's a single copy) wasn't easily testable, it tightly couples the class existence to the program's lifecycle. To test it, you must adhere to the program's launch and shutdown, which often has side effects unimportant to testing the class. If it was effectively as singleton (one copy in the program, but not enforcement otherwise), you could create multiple copies at test time without the program, verifying that behavior across the class is as-it-should-be for each testing scenario.Iron
E
4

The issue of 'Statics being evil' is more of an issue about global state. The appropriate time for a variable to be static, is if it does not ever have more than one state; IE tools that should be accessible by the entire framework and always return the same results for the same method calls are never 'evil' as statics. As to your comment:

I find static variables more convenient to use. And I presume that they are efficient too

Statics are the ideal and efficient choice for variables/classes that do not ever change.

The problem with global state is the inherent inconsistency that it can create. Documentation about unit tests often address this issue, since any time there is a global state that can be accessed by more than multiple unrelated objects, your unit tests will be incomplete, and not 'unit' grained. As mentioned in this article about global state and singletons, if object A and B are unrelated (as in one is not expressly given reference to another), then A should not be able to affect the state of B.

There are some exceptions to the ban global state in good code, such as the clock. Time is global, and--in some sense--it changes the state of objects without having a coded relationship.

Euratom answered 11/8, 2011 at 23:7 Comment(2)
"Time is global" -- there are other ways to model time in computing systems than to have it be some implicit, global thing that changes on its own. cf. this survey: "Modeling Time in Computing: A Taxonomy and a Comparative Survey" @ arxiv.org/abs/0807.4132Maes
Although actual time is is, for most terrestrial applications, a global concept, many functions that would use actual time in production applications may need to use "simulated" time for some kinds of testing. If one wants to confirm how a time-clock application will handle transitions into and out of daylight saving time, being able to have it use a virtual clock which can be set independently from a machine's actual clock can make testing much easier than if one has to either mess with a computer's actual clock or wait for daylight saving time to begin or end.Critta
M
4

everything (can:) have its purpose, if you have bunch of threads that needs to share/cache data and also all accessible memory (so you dont split into contexts within one JVM) the static is best choice

-> of course you can force just one instance, but why?
i find some of the comments in this thread evil, not the statics ;)

Menado answered 15/8, 2011 at 21:38 Comment(0)
A
4

My $.02 is that several of these answers are confusing the issue, rather than saying "statics are bad" I think its better to talk about scoping and instances.

What I would say is that a static is a "class" variables - it represenst a value that is shared across all instances of that class. Typically it should be scoped that way as well (protected or private to class and its instances).

If you plan to put class-level behavior around it and expose it to other code, then a singleton may be a better solution to support changes in the future (as @Jessica suggested). This is because you can use interfaces at the instance/singleton level in ways that you can not use at the class level - in particular inheritance.

Some thoughts on why I think some of the aspects in other answers are not core to the question...

Statics are not "global". In Java scoping is controlled separately from static/instance.

Concurrency is no less dangerous for statics than instance methods. It's still state that needs to be protected. Sure you may have 1000 instances with an instance variable each and only one static variable, but if the code accessing either isn't written in a thread-safe way you are still screwed - it just may take a little longer for you to realize it.

Managing life cycle is an interesting argument, but I think it's a less important one. I don't see why its any harder to manage a pair of class methods like init()/clear() than the creation and destroying of a singleton instance. In fact, some might say a singleton is a little more complicated due to GC.

PS, In terms of Smalltalk, many of its dialects do have class variables, but in Smalltalk classes are actually instances of Metaclass so they are really are variables on the Metaclass instance. Still, I would apply the same rule of thumb. If they are being used for shared state across instances then ok. If they are supporting public functionality you should look at a Singleton. Sigh, I sure do miss Smalltalk....

Akira answered 17/8, 2011 at 19:53 Comment(0)
B
4

There are two main questions in your post.

First, about static variables. Static variables are completelly unnecesary and it's use can be avoided easily. In OOP languajes in general, and in Java particularlly, function parameters are pased by reference, this is to say, if you pass an object to a funciont, you are passing a pointer to the object, so you dont need to define static variables since you can pass a pointer to the object to any scope that needs this information. Even if this implies that yo will fill your memory with pointers, this will not necesary represent a poor performance because actual memory pagging systems are optimized to handle with this, and they will maintain in memory the pages referenced by the pointers you passed to the new scope; usage of static variables may cause the system to load the memory page where they are stored when they need to be accessed (this will happen if the page has not been accesed in a long time). A good practice is to put all that static stuf together in some little "configuration clases", this will ensure the system puts it all in the same memory page.

Second, about static methods. Static methods are not so bad, but they can quickly reduce performance. For example, think about a method that compares two objects of a class and returns a value indicating which of the objects is bigger (tipical comparison method) this method can be static or not, but when invoking it the non static form will be more eficient since it will have to solve only two references (one for each object) face to the three references that will have to solve the static version of the same method (one for the class plus two, one for each object). But as I say, this is not so bad, if we take a look at the Math class, we can find a lot of math functions defined as static methods. This is really more eficient than putting all these methods in the class defining the numbers, because most of them are rarelly used and including all of them in the number class will cause the class to be very complex and consume a lot of resources unnecesarilly.

In concluson: Avoid the use of static variables and find the correct performance equilibrium when dealing with static or non static methods.

PS: Sorry for my english.

Blight answered 5/1, 2014 at 12:18 Comment(0)
L
4

There's nothing wrong with static variables per se. It's just the Java syntax that's broken. Each Java class actually defines two structures- a singleton object which encapsulates static variables, and an instance. Defining both in the same source block is pure evil, and results in a code that's hard to read. Scala did that right.

Lemmon answered 12/2, 2014 at 12:33 Comment(0)
R
4

Static variables are not good nor evil. They represent attributes that describe the whole class and not a particular instance. If you need to have a counter for all the instances of a certain class, a static variable would be the right place to hold the value.

Problems appear when you try to use static variables for holding instance related values.

Rivera answered 25/4, 2017 at 14:30 Comment(0)
I
3

a) Reason about programs.

If you have a small- to midsize-program, where the static variable Global.foo is accessed, the call to it normally comes from nowhere - there is no path, and therefore no timeline, how the variable comes to the place, where it is used. Now how do I know who set it to its actual value? How do I know, what happens, if I modify it right now? I have grep over the whole source, to collect all accesses, to know, what is going on.

If you know how you use it, because you just wrote the code, the problem is invisible, but if you try to understand foreign code, you will understand.

b) Do you really only need one?

Static variables often prevent multiple programs of the same kind running in the same JVM with different values. You often don't foresee usages, where more than one instance of your program is useful, but if it evolves, or if it is useful for others, they might experience situations, where they would like to start more than one instance of your program.

Only more or less useless code which will not be used by many people over a longer time in an intensive way might go well with static variables.

Impenitent answered 11/8, 2011 at 19:49 Comment(0)
O
2

All the answers above show why statics are bad. The reason they are evil is because it gives the false impression that you are writing object oriented code, when in fact you are not. That is just plain evil.

Owensby answered 11/8, 2011 at 16:47 Comment(4)
But does rigidly considering your code to follow some arbitrary standard paradigm actually make the code better, or are we complaining to avoid just writing code that works?Hannie
Yes it does make it better, because it makes it more manageable in the future, more easier to understand, and more explicit.Owensby
Why is it evil not to write OO code? and why doesn't Bjarne Stroustrup agree with you? to name just one ...Agrology
I didn't say its evil not to write OO code. I said its evil to think you are writing OO code, when all you are is disguising globals behind static methods and properties. Please re-read what I wrote.Owensby
B
2

There are plenty of good answers here, adding to it,

Memory: Static variables are live as long as the class loader lives[in general till VM dies], but this is only in-case of bulk objects/references stored as static.

Modularization: consider concepts like IOC, dependencyInjection, proxy etc.. All are completely against tightly coupling/static implementations.

Other Con's: Thread Safety, Testability

Become answered 31/1, 2016 at 11:38 Comment(0)
S
2

I've played with statics a lot and may I give you a slightly different answer--or maybe a slightly different way to look at it?

When I've used statics in a class (Members and methods both) I eventually started to notice that my class is actually two classes sharing responsibility--there is the "Static" part which acts a lot like a singleton and there is the non-static part (a normal class). As far as I know you can always separate those two classes completely by just selecting all the statics for one class and non-statics for the other.

This used to happen a lot when I had a static collection inside a class holding instances of the class and some static methods to manage the collection. Once you think about it, it's obvious that your class is not doing "Just one thing", it's being a collection and the doing something completely different.

Now, let's refactor the problem a little: If you split your class up into one class where everything is static and another which is just a "Normal Class" and forget about the "Normal Class" then your question becomes purely Static class vs Singleton which is addressed in length here (and probably a dozen other questions).

Siren answered 28/10, 2019 at 21:41 Comment(0)
S
2

Static fields are de facto GC roots (see the How Garbage Collection Works section earlier in this chapter), which means they are never garbage-collected! For convenience alone, static fields and collections are often used to hold caches or share state across threads. Mutable static fields need to be cleaned up explicitly. If the developer does not consider every possibility (a near certainty), the cleanup will not take place, resulting in a memory leak. This sort of careless programming means that static fields and collections have become the most common cause of memory leaks!

In short, never use mutable static fields—use only constants. If you think you need mutable static fields, think about it again, and then again! There's always a more appropriate technique.

Skijoring answered 22/5, 2021 at 13:32 Comment(0)
A
1

I think excessive uses of global variables with static keyword will also leads to memory leakage at some point of instance in the applica

Analysand answered 11/10, 2017 at 12:13 Comment(0)
Q
0

Suppose that if you have an application with many users and you have defined a static function that saves state within a static variable, then every user will modify the state of other users.

Quesnay answered 7/8, 2015 at 7:51 Comment(1)
But in instances where you're using static variables, you usually want the state to be overridden, e.g. a global state that applies to all users.Weigh
P
0

From my point of view static variable should be only read only data or variables created by convention.

For example we have a ui of some project, and we have a list of countries, languages, user roles, etc. And we have class to organize this data. we absolutely sure that app will not work without this lists. so the first that we do on app init is checking this list for updates and getting this list from api (if needed). So we agree that this data is "always" present in app. It is practically read only data so we don't need to take care of it's state - thinking about this case we really don't want to have a lot of instances of those data - this case looks a perfect candidate to be static.

Prudence answered 1/11, 2018 at 16:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.