The main bad habit is a gross overuse of patterns to compensate for language stupidity (see: http://norvig.com/design-patterns/).
A few particular examples include:
- Too much global state. You call it a Singleton. I call it a global variable with a fancy name and a lot more code.
- You lose the ability to think functionally and dynamically. You can see the core of the architecture much more clearly if your default thought is 'I want to pass a function' or 'I want to call a fn based on rutime types.' And then you should convert that to what's implementable in language X (strategy pattern and visitor pattern, respectively for Java). Thay way you don't lose sight of the forest for the trees (and can implement what you're trying to do without cruft in a good language).
- Verbosity. It's bad enough that passing a small fn (1 line of code in a decent language), requires a separate class and 20 lines of code in Java. On top of that the type system is too weak to actually stop most interesting errors but just strong enough to be annoying. And for some idiotic reason, they won't even implement compile time type inference which would save lots of verbosity and maintain code/bytecode compatibility.