One thing I'd add, is that Java is very amenable to static code analysis, and there are good tools like PMD and FindBugs for Java. I always encourage teams using Java to use one or both. The biggest downside is that you usually have to tweak the rule-sets to avoid getting lots of false positives. And if you get too many false positives then people tend to stop paying attention to the notifications from the tool.
On a related note, I really encourage Java teams to shoot for a goal of having compiles that finish with no warnings. If there are generic warnings littering your code (like, for example, all the warnings about unqualified references to generic types that you get when using code written before generics existed), bite the bullet and either fix them, or make it explicit that you don't care and add the appropriate annotations to turn them off. At least that way, when a new, interesting warning shows up, maybe people will pay attention to it.
And yes, this is something of a "do as I say, not as I do" thing, as I have definitely written Java code that doesn't follow this rule. Especially on my personal projects or code where I'm not working with a big team. On bigger projects, I do try to push that as much as I can, depending on my role on the project.
> [...] Java is very amenable to static code analysis [...]. The biggest downside is that you usually have to tweak the rule-sets to avoid getting lots of false positives.
These two statements seem to be in opposition to each other.
(All your advice is spot on. If you let warnings remain in code, you'll just end up accumulating more and more warnings until it's too much to fix. I guess it's a sort of "broken windows" effect.)
I don't know if they're in opposition exactly. The Java language is definitely amenable to static analysis to some extent, probably more so than a more dynamic language. But a lot of the "false positives" are just about what rules the developers of the tool ship by default, and what they define as a "bug" (or "possible bug"). For better or for worse, static analysis tools sometimes conflate simple stylistic issues ("don't use variable names less than two characters") with things that are likely to be actual logic errors. And since the tool will always be limited in how much it can understand about the intent of the code, it's pretty much always just applying heuristics and a probabilistic analysis, even when processing Java.
So yeah, those tools aren't perfect, but my subjective experience has been that they help, as long as you tweak the knobs so that they don't just generate something equivalent to the "broken windows" compiler warnings, etc.
My point was basically that, in general, imperative programming languages (like Java) are insanely hard to do static analysis on, so I though it was ironic that you mentioned that it (Java) was both a) amenable to static analysis, and b) said that it resulted in a lot of false positives. I think that point b) somewhat invalidates point a), don't you think?
EDIT: False positives tend to indicate that there's something wrong with your analysis.
I suppose this is a general thing: If a warning system alerts you every five minutes, what are you going to do? Are you going to react and go on full-adrenaline-rush every five minutes, or are you just going to turn it off after two or three false alarms?
On a related note, I really encourage Java teams to shoot for a goal of having compiles that finish with no warnings. If there are generic warnings littering your code (like, for example, all the warnings about unqualified references to generic types that you get when using code written before generics existed), bite the bullet and either fix them, or make it explicit that you don't care and add the appropriate annotations to turn them off. At least that way, when a new, interesting warning shows up, maybe people will pay attention to it.
And yes, this is something of a "do as I say, not as I do" thing, as I have definitely written Java code that doesn't follow this rule. Especially on my personal projects or code where I'm not working with a big team. On bigger projects, I do try to push that as much as I can, depending on my role on the project.