Q:

When should a class be final?

I've only really seen this on Java's wrapper classes (String, Integer, etc.), but never in open-source projects, and I was never taught about it in any books or classes. I know it means the class can't be extended, but I don't know when that would be useful for any class outside the aforementioned JVM-low classes. So, when would I want to use the final modifier on a class, if ever?

A:

Whenever you don't want the class to be extended.  Designing for extension has a cost (see also Eric Lippert's Blog: Why Are So Many Of The Framework Classes Sealed?) - you need to make sure you provide the right hooks for the class, that people can implement those hooks without breaking things, that you can be reasonably sure that subclasses won't be nefarious (this is especially important with core language classes like String and Integer), that the contracts that the superclasses implement are clear (so that subclasses don't break them easily).
This takes work, time, and thought to put into it.  It isn't easy developing a class that is meant to be extended.  And sometimes, you know you don't want it to be extended - that it can be put to nefarious use and cause havoc with your implementation if someone passes you a mutable String rather than an immutable one.
And so, you make the classes final.  There can be no mutable String, because its an immutable class and its final.  You know when you get it, it won't be changed from under you in some way.  You can save it and be sure that that it will behave like a String, always - no subclasses can be made to make it be otherwise.
Thus, there is a bit of design that some follow that all classes start out as default to be final.  How often are you going to subclass that DTO? And when you do want to subclass it for some reason, you should spend some time thinking about the implications of removing the modifier.
There is a check style  rule Design For Extension.  Personally, I like it.  In every non-final class, every method must be one of:

abstract
final
empty implementation

This sort of thinking then allows you to write subclasses that are clearly implemented the proper way - providing hooks and preventing the superclass fro being broken by the subclass not knowing about tinkering the innards of it in an unexpected way.  Though, admittedly, this design philosophy means that the subclasses are more limited in their flexibility - but they can't corrupt the state of their superclass.
Again, if you're not prepared or willing to design a class so that it can be extended cleanly, it is best to design the class so it can't be extended at all.

