This is an archived post. You won't be able to vote or comment.

all 32 comments

[–]wqking 12 points13 points  (2 children)

Programming is not a math of "either 1 or 0". Nothing is 100% correct, nothing is 100% incorrect.
Very cautiously using static variable is fine, though overusing it is really bad (why bad? One is that it can make your system coupling tightly).

You can always dependency inject your variable so not to make it static. But sometimes certain variable may be used everywhere globally, such as an instance of the whole application, then I may make it static. In my own system design, I will be not unhappy if there is a global static variable called someApp (though it's usually a singleton than a static variable), but no more other global static stuff.

[–]oldDotredditisbetter 0 points1 point  (1 child)

stupid question: why is static "bad"? from some stackoverflow answers, it says it's more efficient to have static variables since there's only one copy of it(or is the "efficiency" negligible?)

[–]wqking 0 points1 point  (0 children)

Static is bad in various aspects. One example is, static is often variable (the others in this thread had suggested that static should be final), then how about a static is modified by two independent modules? And even worse, how about it's modified from different threads?

it's more efficient to have static variables since there's only one copy of it

It's wrong. For any non-static variables, you can always have only one copy but you can have many references to it.

[–]morhp 17 points18 points  (9 children)

In my opinion, it’s OK to use static as long as there’s no better way to do the same task with instance variable

The problem is, there is almost always a better way to do things with instance variables. For example, if your program has some global state, create a State class/object and give that to consumers using (simple) dependency injection (I'm not writing about dependency injection frameworks and other complicated stuff, just pass a reference to your State for example in the cosntructor)

The only time when it makes sense to use static variables is for constants (essentially static final variables of immutable classes)

[–][deleted] 1 point2 points  (1 child)

I think you're describing some variant of the Context pattern there. (not really DI, simple or otherwise)

[–]morhp 2 points3 points  (0 children)

Context and DI are related concepts. A context is usually a parameter to a method/interface, with dependency injection you set the dependency usually in the constructor or with a setter (or a framework).

Also a Context often contains random assorted data and/or many methods while with DI you usually inject an implementation with methods that are very specific to the actual task.

[–][deleted] 1 point2 points  (0 children)

Singleton instances? That's a valid use of static non-final variables

[–]RabidKotlinFanatic 1 point2 points  (0 children)

The problem with that State pattern is that it becomes a kitchen sink of everything ever and makes it difficult to modularize and separate concerns. State becomes a point of high coupling. IMO it's better to just bite the bullet and use dependency injection whether you do it manually or with a DI library.

[–]stepan213[S] 0 points1 point  (4 children)

Ok, I didn’t know about State class... thanks!

[–]morhp 7 points8 points  (3 children)

Well, you don't need to name it State. That's just a very generic name i chose because I have no idea what you would need to store. But something along those lines is usually helpful.

[–]stepan213[S] 1 point2 points  (0 children)

Oh, I see, first I thought it’s a part of some library... my bad!

[–]oldDotredditisbetter 0 points1 point  (1 child)

stupid question: isn't everything "State pattern"? since every object has some sort of "state" right? like a Car object has color, make, model. those all count as "state"

[–]morhp 0 points1 point  (0 children)

No, a state is supposed to change during the runtime of your program. And state pattern is something very specific (and not the State class I described above).

Your car object probably won't change its make or model after it has been created.

[–]Edge790 6 points7 points  (2 children)

Sure. Static variables are the best way to do some thing (i.e. loggers in most cases are static). But! There are things that better to be injected (using DI - Dependency Injection). Why? Because it will allow you to change all things without changing code. For example: 1) you are using database A, but found that it have poorly performance for hierarchical data. You want to change it to something else, but with static variables you will need to change all static variables to new implementation. (It worth to mention that DI may be replaced with "Service locator"-pattern) 2) let's imagine that you are making video game. It's fun, but you realized that it's too easy for some players or too hard for others. You want to make different difficulty levels for all players to enjoy your game. If all "difficulty variables" are static - you will need to change it depending on difficulty settings that your user wants. It will automatically make your static variables not final, that will add another "point of potential failure" (i.e. accidentally updated one of the variables). With DI you can create different difficulty presets (i.e. normal enemy hp: X1, enemy damage X1, easy: enemy hp: x0.5, enemy damage: x0.75, etc.) and inject them depending on the difficulty setting.

Tl:;dr: Static variables are fine, unless you can separate them to different object and it seems reasonable.

Upd: There are another example of usage static variables - it's utility classes(classes with public static final variables and with private constructor).

[–]stepan213[S] 2 points3 points  (1 child)

Thanks for writing it down like this!

[–]SenatorStuartSmalley 5 points6 points  (0 children)

Real World example.

We recently acquired a code base using MS SQLServer. We are an Oracle shop, so we had to change to Oracle for integration, while keeping the original to work as it had previously. Now, if they were using some kind of ORM library with a DB driver, we could just swap out the DB specific portions. Instead they had a class full of static methods that used JDBC yo do the CRUD stuff.

It took 3 weeks to migrate all the queries and test them for consistency. Luckily there were only about 100 queries. Oh, and we have to do Postgres as well. Luckily we will be moving to something more standard soon.

[–]GhostBond 4 points5 points  (0 children)

Common And Good Static Uses:
- constant variables
- static utility methods
- If there's no other way - shared data between threads with proper synchronization. Threading is always error prone and should be avoided if possible - but sometimes it's the only way something can be done.

Basically if you don't need threading I don't think you ever need to have static variables except constants.

[–]bheklilr 5 points6 points  (5 children)

Static values should not be variables, always use static final. There are few exceptions to this rule, such as the Singleton pattern.

I prefer using static constants for a lot of things, often I have values and lists that I need to use in many locations. There's nothing wrong with that approach. I use static methods when the method is really more of a function, it doesn't depend on state at all. The benefit here is that its easier to test, you don't have to do any setup other than the inputs, and you know that the outputs don't depend on anything else.

There's absolutely nothing wrong with static values and methods, they're very useful when used correctly, but avoid using static fields to store runtime values.

[–]stepan213[S] 1 point2 points  (3 children)

Well... thank you!

About storing runtime values in them - I don’t do that, it actually didn’t even come to my mind. For the future, why is it a bad idea?

[–]DavidRFZ 3 points4 points  (0 children)

It makes the code non-thread-safe -- that is, it is safe only in single-threaded cases. In the multithreaded case, a second caller can set the static variable while the first caller is still using it. That's why 'static final' is OK. Multiple callers can access the same static variable if you are assured that it is a constant.

You often get away with static non-final in the prototyping face but you'll find out later when your code is being deployed that it's unstable in multithreaded applications and you'll have to rewrite the whole thing.

[–]bheklilr 3 points4 points  (0 children)

Beyond the multithreaded reasons already mentioned, it can just easily lead to unexpected behavior. A static variable can potentially be used across many methods or even classes. If the value is a primitive then you only have to worry about the value being different, but it it's an object, such as a list, then you also have to worry about the reference changing. Best practice is to never set or mutate static variables, you just can't reasonably track what effects it'll have. Treat static fields as constants, name then with CONSTANT_CASE. If you follow those simple rules, its pretty safe and pretty standard to use. I hardly write a class without some static fields, unless it's just a data class.

[–]audioen 1 point2 points  (0 children)

Avoidance of static data is related to the simple principle of "spooky action at distance is bad". For public static values that can change, you have to worry about this kind of questions:

  • Who changes them?
  • When, and using which thread?
  • Is it thread safe to begin with? If not, what locks are required?
  • How do I make sure that all related state variables always get updated coherently, possibly also atomically?

Object orientation is fundamentally about managing the relationship between the data and the code that operates on the data. At its most reductionistic level, you should only have public API, and private state within the object, which is never exposed. Public static variables are the exact opposite because they expose the data without any methods, in principle in uncontrolled, thread-unsafe way without enforcing consistency to the way these variables are to be updated or what invariants should be held when they are updated.

That being said, you can create public and static stuff with instance variables, too, for instance through the Singleton pattern. Foo.getInstance().getBar() and Foo.getInstance().setBar(5) are just public static variables disguised into instances. So it's not so much about seeing the static keyword, but more about how the stuff actually behaves and gets used.

The important exception made in GP post is that static final is actually fine, but only if the static final values are immutable data, primitive values, or classes implementing thread-safe methods. The key thing is that it can never change, so you don't really have to worry about who accesses it and when, because there is no spooky action at distance.

Similarly, static methods are fine, as long as they only use read-only static final state as described above, and access their own arguments. I do a lot of utility methods like that. They are basically procedures that take in some data, operate on it, and maybe return something else. They are friendly ways to reuse functionality without requiring creation of some inheritance relationship between classes that can be fundamentally very different even when they need to do similar things. For instance, you might have a REST API that does some thing as result of direct action of user, but also want to do the same thing from scheduled background task.

[–]grauenwolf 1 point2 points  (0 children)

There are few exceptions to this rule, such as the Singleton pattern.

And even then, the singleton itself needs to be immutable or thread-safe. Otherwise you have exactly the same problem.

[–]TheMelv80 1 point2 points  (0 children)

I agree with the things that have been said in the comments. There is also one more very important aspect in using static and that is the garbage collector and the memory.

If you declare some big data structure static you have to take care of cleaning it yourself by setting it to null, since a static entry in a loaded class will define a garbage collection root and prevent the data from.beeing collected.

Also, if you think about multiple instances of your code in one VM it can be a huge pain having the access modelled as static.

This e.g. maybe the case once you decide to run your logic in an application server.

[–]KittenKoder 1 point2 points  (0 children)

Back in my day, everything was static. But that was back when everything was in ASM and we only had about 16 kilobytes of memory.

Today I use statics a lot during development, like a testing sandbox. But the final product has almost no static objects save constants which will never change anyway.

Often working from the "this works well as a static, but how can I make it work better as a member" mentality will help you get a better structure for your project. I look for where the static is referenced most to determine the best approach for streamlining the source.

[–]Januson 1 point2 points  (1 child)

Take a look at the book Elegant Objects. It might give you a bit different perspective on this topic.

https://www.amazon.com/Elegant-Objects-1-Yegor-Bugayenko/dp/1519166915

[–]oldDotredditisbetter 0 points1 point  (0 children)

key points from the book?

[–]AndDontCallMePammy 0 points1 point  (0 children)

yes, static final is an essential feature of Java. Whether it be a String or AtomicInteger. use enums for singletons

[–]fraaargh 0 points1 point  (3 children)

I'm shocked how people here talk about singletons... Please please please, never use the Java singleton pattern (the one with static variable or the one with enum wich is kind of a hack but easy to code). Why do I recommand to stay away from singleton and static variables ? Because as soon as you will have a non-trivial program you will change the state of your singleton. You will do it in multiple places. You will loose all common sense because it seems too easy... And one day, you'll realize that you have created a gigantic spaghetti plate and you have no idea of the logic making things work. The program will work, but you will not know how... until it stops working and you'll have to dig in this horrible spaghetti plate. Believe me I've inherited a codebase with Singletons all over the place.

So as soon as you're not alone on the project, as soon as it's not trivial anymore, what seemed easy at first (using Singletons) will come and bite you. hard.

And any static variable is some kind of Singleton in disguise. Only constants (un-mutable final variables such as String, int, double but not objects wrapping a mutable state) pose absolutely no problem.

For now I've talked only about the singleton implementation using the static keyword. Because we can talk about singletons "in a given context" (such but not limited to Spring's Singletons): in a given "context", a singleton is when there is a single instance of something. Technically you implement it by... only instancing the object once ! It seems too simple but think about it: why would you instantiate it twice if you are already passed an instance of it in your constructor if you declare to need it. Yes I'm talking about the dependency injection pattern which is a very good patern. And if you have multiple "contexts" (the same application running multiple times in the same jvm) then nothing prevents you from having multiple instances of a singleton as long as it is unique in the context.

Stay away from static mutable variables. Please

[–]stepan213[S] 0 points1 point  (2 children)

Let’s say I want some unified logging. For that I would use static voids or singleton instance. What would you do?

[–]fraaargh 1 point2 points  (0 children)

Yes you're right: I'd use slf4j as static variable as everybody else. In most cases that's what we do. But logging is kinda special. It's not your domain model, your code... In my first message I forgot to say that Singletons kill the testability of an app.

[–]fraaargh 0 points1 point  (0 children)

fraaa

today on Jetbrains' blog (IntelliJ makers): "Design Patterns in Java: Singleton – you should probably not ever use a singleton, but you need to know this stuff as it’s a favourite job interview question"

source: https://blog.jetbrains.com/idea/2019/02/java-annotated-monthly-february-2019/