This answer is just a verbatim quote of text by Richard Bair, one of the JavaFX API designers, which was posted on a mailing list in response to the question: "Why is almost everything in the [JavaFX] API final?"
Subclassing breaks encapsulation. That's the fundamental reason why
you must design with care to allow for subclassing, or prohibit it.
Making all the fields of a class public would give developers
increased power -- but of course this breaks encapsulation, so we
avoid it.
We broke people all the time in Swing. It was very difficult to make
even modest bug fixes in Swing without breaking somebody. Changing the
order of calls in a method, broke people. When your framework or API
is being used by millions of programs and the program authors have no
way of knowing which version of your framework they might be running
on (the curse of a shared install of the JRE!), then you find an awful
lot of wisdom in making everything final you possibly can. It isn't
just to protect your own freedom, it actually creates a better product
for everybody. You think you want to subclass and override, but this
comes with a significant downside. The framework author isn't going to
be able to make things better for you in the future.
There's more to it though. When you design an API, you have to think
about the combinations of all things allowed by a developer. When you
allow subclassing, you open up a tremendous number of additional
possible failure modes, so you need to do so with care. Allowing a
subclass but limiting what a superclass allows for redefinition
reduces failure modes. One of my ideals in API design is to create an
API with as much power as possible while reducing the number of
failure modes. It is challenging to do so while also providing enough
flexibility for developers to do what they need to do, and if I have
to choose, I will always err on the side of giving less API in a
release, because you can always add more API later, but once you've
released an API you're stuck with it, or you will break people. And in
this case, API doesn't just mean the method signature, it means the
behavior when certain methods are invoked (as Josh points out in
Effective Java).
The getter / setter method problem Jonathan described is a perfect
example. If we make those methods non-final, then indeed it allows a
subclass to override and log calls. But that's about all it is good
for. If the subclass were to never call super, then we will be broken
(and their app as well!). They think they're disallowing a certain
input value, but they're not. Or the getter returns a value other than
what the property object holds. Or listener notification doesn't
happen right or at the right time. Or the wrong instance of the
property object is returned.
Two things I really like: final, and immutability. GUI's however tend
to favor big class hierarchies and mutable state :-). But we use final
and immutability as much as we can.
Some information: