I just escaped static hell after way too many hours of frustration. I write this as a map to help you escape static hell much easier than I did. As I am far from being a java guru, if you see a better way or have an issue with my methods, by all means pile in.

Because your Java program starts execution with a block something like, 'public static main(String args) { }' , Java sets you on the road to static hell. The experts will give you philosophical reasons why static variables and methods are wrong. I am not an expert by any means, so my reasons are plain and simple. The first reason why static is evil is static creep.

Static creep happens when you get an error that wants to to change a variable or method to static in order to resolve an error. Static is an addictive state in Java. The first two 'public static int whatevers' were free, but then you had to have a getter or a setter and suddenly you are on the road to static hell. Every change or addition wants to be static and when you finally try to make a constructor, you find that the word 'new' and the word 'static' don't play well together. So you try to reduce the static and you discover the real catch, static cling!

Static cling happens when you try to fix your static filled code from the bottom up. You fix stuff until the code saves without error and then it blows up with a null from nowhere when you run it. If you are not real careful, you can easily thrash your code into meaningless gibber while chasing down and trying to comprehend where you went wrong. If every other line in your code resembles 'system.out.println("it got past this part and x is now " + stupidValue)' you know exactly what I mean. Once you figure out where you need to inject a proper linkage to avoid the null, unless your initial source for the linkage is clean, static creep sets right back in.

Here is a game engine example of how to escape static. This game engine consists of 6 objects; Game, GameEngine, Play, Canvas, GameLoop and GameContext. They key to escaping static is the GameContext object.

GameContext.java is how we escape from static hell. GameContext.java contains all or most of the variables and methods that would have been static. It also has all the appropriate getters and setters. The GameContext method can initialize objects and set this.whateverObject = whateverObject so that the initialized object can be referenced later. Your game might be better organized with GameContext divided out into a few similar objects but the function remains the same and the core context object can initialize and provide links to the other context objects.

Game.java is the central object passed to methods in order to link the various processes. Game has the main block in it. Game calls GameEngine.Java and passes itself and a new Play to it. 'GameEngine.start(new Play());.' By creating and passing Play in this manner, we have now excaped the static realm and everything else can be free of static.

GameEngine.java sets up the canvas and starts the game loop passing itself and Canvas.java to GameLoop.java.

Play.java extends Game.java and is where the engine becomes personalized to the game. If you keep the modifications and expansions of your engine as generic as possible, you can reuse it for other games you write. Ideally Play and GameContext are the two parts of the engine that bridge between the basic engine functions and your game. As you extend your game, alway keep in mind that generic additions might be more useful if added to the engine, and specific additions should remain outside the engine. Since Play.java extends GameEngine.java, generic functions can be maintained in GameEngine.java and Play.java can have the same function personalized with a '@Override' in front of them. Play.java has the generalized methods for render and update that should probably point to render and update objects. Updated properly, Play is where drastic changes to the game can be made and reversed with relative ease.

Canvas.java is the graphic object and starts with 'public class GameCanvas extends JComponent implements ComponentListener {.' Canvas has all the listeners so Canvas is not only the object to refer to for display, it is the object to go to for interaction with the display.

GameLoop.java calls all of the background processes that make the game run. GameLoop calls a routine in Play.java to redraw everything and a routine in Play.java to update game status over and over again. A good primer on game loops can be found here, http://www.java-gaming.org/index.php?topic=24220.0

Now to string it all together all the classes that need it have a 'Game game; defined and set by either a setter or by having it passed as a parameter and set with the line 'this.game = game;.' The Game class has the line 'Context context = new Context();.'

Since Play extends Game, when play runs the line 'context.setPlay(this);.' game.context.getWhatever()' and 'game.context.setWhatever()' can pass to any objects that have the parameter game and 'this.game = game;' as part of the construct.

If the object you are working on is going to be large the line 'GameContext gc = game.context;' can make it pretty easy to access the pool of variables. Writing something like gc.getDataYouWant() to call up a value is pretty easy and an entire range of potential static errors can be evaded. All this and the Guru's will tell you that you have avoided the slew of security, testing and philosophical issues that static variable present.

An instance of a logger makes sense as a static member. The logger itself should not consist of static methods, unless you're fine with Baby's First Logger. Really though, there is no "static hell": it should not present some kind of engineering challenge to avoid writing everything as static methods. It's very much OOP 101, something you should be getting the hang of by the time you've done a tutorial or two.

How about multiple loggers? Look at any logging system like log4j and you'll see ways of turning loggers on and off by level or by the class they're contained in and pointing them at different files, system loggers, etc. But if a hardwired implementation with no support for levels, facilities, or appenders is fine for you, then yeah I guess you could implement it with one or two statics.

Programming style is very important, and static methods actually is part of the reason why Java remains very flexible.

The biggest bane to static programming that I've seen is its harmful to unit tests. If you rely heavily on unit tests, static classes will make it pretty difficult to set up into test suite. They can cause threading problems as well, and data has to be controlled with much finer detail when dealing with static variables and functions.

It isn't all bad...

Static classes allow you to transfer functionality of one class to many classes that might need the same thing (like error logs). As long as you keep track of how you are using static classes, they allow you to essentially "script" some OOP functions. In some cases, you'll be able to solve a lot of problems faster with static calls because it'll drastically reduce singletons when used correctly.

Like all facets of programming, you have to research and look at the benefits and the downsides of everything before you use it. Not only will you learn more about it, but it will also improve your programming knowledge as well.

As for me, I like static because it helps me reduce the amount of code I have to write. It isn't for all aspects of coding, mind you. I like using static to keep some items separate from the main engine. Sometimes it is very beneficial to only have to initialize an object once and use that object for different parts of the program (like Loggers).

every programmer starts out using static all the time. When others are telling them that static is bad and they shouldn't use it, they don't listen because they have so many "good" arguments why static is the perfect tool. A few years later they aren't using static anymore and trying to convince the new ones...

p.s. when you already use static everywhere pls try not to have any static/global state. This means don't have any static variables(only with final)

If I have a player class, and it needs to access ONE function in some irrelevant class for some purpose, am I really goin to go and add a field for that class, add an argument to my constructor, and then do the same for every class that references that constructor?!

No.

Static is good, when used appropriately.Personally, in my 'main' game class, which stores the player and the entity/world/whatever managers, I have a static reference to that class (so it's pretty much a singleton) so I can access that one function in the otherwise irrelevant class.

And what about math functions? Should I create a whole new object every time I want to find the magnitude of two coordinates (in a situation where I don't need to create a new vector)?Random functions? Do I need to create new objects for that? Or should I add yet another object to my now bloated constructor.

Worst of all: Constants. How do I do these without static?

newConstants().CONSTANTNAME

?

Now, don't read this wrong. Static has to be used wisely. But saying to never use static is (more) stupid compared to always using it.

Using static to make the compiler happy is a sign of n00b-programming. (If you did this before and realised your mistake, this is not meant to be offensive)

If you keep trying to avoid static, you're going to end up in non-static hell.

am I really goin to go and add a field for that class, add an argument to my constructor, and then do the same for every class that references that constructor?!

That's precisely the situation NOT to use static; if code in instance class A needs to access something in instance class B yet has no reference to it, then your class dependency coupling is wrong. Introducing a static in this situation will bite you in the ass sooner or later, because you're masking a more serious design flaw.

How about multiple loggers? Look at any logging system like log4j and you'll see ways of turning loggers on and off by level or by the class they're contained in and pointing them at different files, system loggers, etc.

I actually implement the Log manager as a singleton with methods to allow for those functionalities, but just wrap the methods into a static external method so I don't need to worry about calling the Instance getter:

Quote

private void inner_Log(string text) { /* Do something */ }

public static void Log(string text) { Instance.inner_Log(text); }

Its mostly a convenience thing for me, and since the Logger shouldn't be running in production, I don't care much for method call overhead or the like.

Also, @OP: Any part of a programming language specification, even goto, can be useful if used correctly, and any part can be an utter mess if abused. Trying to instill dogmatism in a community by stigmatizing something ("static hell", classy) is hardly productive, specially when your post sounds like you expect to be preaching to the choir and as such be received with confirmation of your position.

Naughty you.

I personally use static methods and classes for standard operations that I expect to be useful. For example, I have a nice static trigonometry class with all sorts of math operations relating to angles, vectors, points, distances, etc... Classes that need to use said operations internally end up referencing the static function, so if I need to tweak an specific algorithm (say, a vector-vector intersection calculation) I don't need to go around tracking all classes that implement it.

I am really going to see just how far I can get without static. I am usually pretty good at debugging things, but the tangled mess I recently created has left me trembling in fear.

Random numbers are no biggie. SimpleRNG produces a fairly sweet set of random numbers. I rather like pseudo-random generators anyway. With the same seed you get the same result. This allows me to examine a random game setup and replicate the ones I really like by using the same seeds. It is quite possible to save a world map by saving two doubles. Most RNG's show their flaws in a multi-thread system. Either they are not thread safe or they end up producing enough of a pattern for you to start guessing what comes next with reasonable odds. once you figure out how to keep cranking numbers between zero and 1, you can make a slightly different generator for each thread. Done well, this can make pseudo random numbers seem pretty random. Pseudo-random generators can be useful in testing as well. Best hidden program change detector I ever saw was based on a random number check. If you want real random numbers record the interval between a players key press events while starting the game and adjust a seed with that result. You can keep measuring user timing to adjust your seeds. This does create a potential testing flaw. Live use is more random than test events.

Guice looks like a a good anti-static laundry sheet for Java. I have no experience with it, but it look pretty sweet. JUnit I love, I just need to use it more. It makes me twice the programmer I would otherwise be.

As far as constants go I rather like using enum so I guess I am avoiding the word static and not all static instances. Enum can be used to give code clarity so I rather like it. Enums don't work well with the word new, but the implicit error checking that goes along with the word enum seems to prevent my doing really stupid things with them that won't show up till much later.

While I am going to make a serious try at being static free, I got over my dependence on philosophical coding limitations years ago. At one time there were two new languages that were neck to neck in competition, C and Forth. I picked Forth. Part of the Forth philosophy was no floating point. It made sense at the time. By keeping important values as a ration of two potentially very large integers you could avoid the rounding errors caused by division until it was time to output a final number. You simply multiplied divisors with the divisor to effect division without having to do it. This was all well and good, but it was a pain when you just wanted quick and dirty and didn't really care that you might be off by a ten thousandth. This was a particularly sad thing since no language before or since has been as good at doing quick and dirty. Forth coders implemented floating point stacks, but floating point was never part of the approved standard.

I have been using static as a way to provide simple access to data that I did not mind being global. Now I only use static if it absolutely has to be global. So far the only thing that has had to be global is the main method.

All this talk about how "Java gurus" will tell you not to use static is garbage. Static is a helpful tool that saves so much time.

Static is there for a reason.It's extremely stupid and a waste of time, if not impossible, to avoid it at all costs.

If you don't know what the reason for something is, find out! Don't go into all the trouble to create some hacky time-wasting workaround. Why would you do that?

Going out of your way to avoid static is stupidity (unless you're doing so as some kind of weird challenge).Telling others, especially beginners, to join you is evil.If you don't know what something is for, and use it wrong, don't go and tell everyone else not to use it.

To summarise my argument:- Static makes coding more efficient.- Static needs to be used sensibly or else you will fail.- If you make a mistake, it's probably your fault, not the tools'.- If you don't know and properly understand what you're talking about, don't be talking about it as someone who does.

If you really want to completely avoid static, by all means go ahead.Just don't drag down other people into your mess with you.

To avoid starting a flame war, I will now apologise for any feelings that may have been hurt by this post. It was not meant to cause (too much) offense. (but if it has, that is a bonus!) Anyway, I hope you learnt something from this. Insults have no real value, and should not be taken seriously unless you completely ignore this post and deny your mistakes. Thank you.

I use do do indirect contract jobs for a big gamedev company. Code is quite rigid. I even have to follow their comment style.

When I sent them preliminary source, it contained singletons ( for a depth-buffer autoincrementer since you can't disable depth buffer testing on the console ). Code was sent back saying to ditch singletons in favor of namespaced statics. Same note also told me to use "intrusive" ptrs in lieu of "shared" ptrs.

I use do do indirect contract jobs for a big gamedev company. Code is quite rigid. I even have to follow their comment style.

...

Code is supposed to make sense.

Code also needs to be easy to maintain. A strict coding style is invaluable for a company where different developers can get their hands on the code.

Speaking from experience here. Nothing ruins your day as finding out a critical section of code is not only built in a completely different style as the rest of the (massive) program, but even the comments are in a language you can't even read!

Static isn't inherintly evil, it is just something that needs to be used intelligently just like everything else in java. For a beginner it can seem so easy to use static because often in simpler projects it can make all of your problems dissapear. Scaling up those faulty techniques causes the nightmares the OP described. In a properly coded program static will probably be required, however it needs to be used correctly otherwise you'll have some headaches later.

Because your Java program starts execution with a block something like, 'public static main(String args) { }' , Java sets you on the road to static hell. The experts will give you philosophical reasons why static variables and methods are wrong. I am not an expert by any means, so my reasons are plain and simple. The first reason why static is evil is static creep.

This situation seems eerily similar to what happened to a co-worker of mine who just recently started programming in Java. First you have to consider why you have a static main (entry) method, then once you understand the why, the how (to avoid static hell) becomes clear.

The main method is the bootstrap/entry function that the JVM invokes in your main class to create an instance of that class when your application starts. The only way to have a member of a class exist independently of an instance is to make the member static. Since the main method is called before an instance of your main class has been instantiated, it must be made static.

Static creep happens when you get an error that wants to to change a variable or method to static in order to resolve an error.

The error you're getting "cannot make a static reference to the non-static field" is because you're trying to access a field within your class that hasn't been created yet. The only part of your class that is in existence is the static main method and any variables that are created within its scope. Instead of declaring everything static to resolve the error, you need to create a new instance of your class, then reference the member variable/function associated with that instance as so:

Looking at the number of results returned by Google when you search for the error message, it would appear to be a common stumbling block, and I seem to recall having the same issue myself when I first got into Java years ago. Once you begin to wrap your head around how Java works, it makes a lot more sense.

As for static methods/members being evil, as many have already pointed out, there are places where static makes logical sense, and is the right tool for the job. The only "evil" aspect comes in when it's misused, and that's more of a reflection of the misunderstanding of the implementer than on the "righteousness" of the feature.

Arthur: Are all men from the future loud-mouthed braggarts?Ash: Nope. Just me baby...Just me.

Any bug that survives Eclipse, Compilation and basic testing I consider a bad bug. The ones that stop you dead in the water and make you start thrashing your code in order to find it, is the type of bug I fear.

One nasty type of bug is the bug that is there all along but works fine initially, is always a horror. Instead of being in the code you just wrote. it is in other code hiding and waiting until the conditions are right or your code has snowballed enough to blow up. By this time your code is big enough for a bug to hide.

Another nasty bug form is the type that exists because of a perceptual understanding that does not match with the actual function of the beast.

My worst static bugs have met both of these criteria. The problem with perceptual understanding of static is subtle. When static creation and dependency gets complex, the order of creation can become critical.

As a simple example here is a class Widget used to build widget objects. It has two errors concealed in the code waiting to blow up as you expand the game.

One error is that using a byte to reference an array of 256 objects is going to work fine until you half fill the array. The game is going to be fairly complex before you reach the level where this is going to break.

The second error I have already stuck in. It is a static error that could not be found without thinking about what static really is and how the java compiler is putting things together.

The second your character trys to place a preSmoggle in the Factory, you are going to get an error. The problem is that the static preSmoggle refers to a smoggle that was defined after the preSmoggle was defined. It is hard enough to find this sort of error when you just added it and it blows up consistently and the issue is laid out in a straight row. If this same sort of issue is spread over several objects, good luck finding it quickly. Even when you know exactly what is blowing up with a null and you know where the offending code is, when the order of the compile can alter the results, the bug can turn into a nightmare.

Every issue is a newbie issue but if you are trying to push your coding skills, Java is huge enough to always provide a new area where you are a newbie. Otherwise solid programmers create eventually obvious but elusive bugs when they found themselves using simple code that they rarely use. Since I usually trying to write code several levels above my skill set, avoiding methods of coding that can sneak compilation issues into the code is just smart.

After I had dealt with the previous bug, I had a bug like this that would work fine one game and blow up the next. I suspect it was the order that the objects were called during game play that made the difference. I finally gave up on finding the bug. I deleted a slew of classes and rewrote them avoiding static. Even with the learning curve of figuring out how to do stuff without static, it took me way less time to recode the classes than I had already spent trying to find the bug.

One error is that using a byte to referencean array of 256 objects is going to workfine until you half fill the array. Thegame is going to be fairly complex beforeyou reach the level where this is going tobreak.The second error I have already stuck in.It is a static error that could not be foundwithout thinking about what static reallyis and how the java compiler is puttingthings together.

ROTFL!

I think most of us here won't reference an index with a byte. That's pretty stupid.

Your trying to "preach" why static is bad when you're second guessing how it works?

Static isn't OO. You can't use static methods in interfaces and can't override them. Static fields are globals: you're asking one value to work for every single member of the class. All this is rather theoretical, of course. Where you get into trouble in real life is when you make your program more complicated; when a simple stand-alone object becomes part of a complex structure.

Basically, you find a subclass needs to override one of the superclass's static classes. Or there's a global value that doesn't apply to one particular class instance.

However, most of the time statics are easy, avoiding them is difficult, your code is not going to get more complicated, and you'd be nuts to pay a big price to avoid them. If you do get into trouble, you can fix it when you do. But when it is time to fix it, fix it or you will be in Static Hell.

Note: a class defined as "static" in Java is something else completely and not a part of this discussion. (Though sometimes people do use the word to mean a class containing only static methods and fields--which is a part of this discussion.)

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org