Because the exception classes that you get in the standard Java library are not always exactly what you want. In a real-world application, you'll probably want to make some custom exception classes for specific error conditions that can happen in your business logic.
For example: I'm working in a project now where we're writing software for a railway company. The software contains some business rules that have to do with how trains travel from one station to the next. We have a database in which the state of all the trains is kept. All trains are identified by a train number.
Suppose that in the GUI somebody enters an invalid train number. When the software tries to lookup the train in the database and it can't find it, it throws a TrainNotFoundException.
That exception gets caught higher up in the application and the user gets a warning in the GUI that (s)he entered an invalid train number.
In fact, the TrainNumberNotFoundException is a subclass of BusinessLogicException, which extends Exception. Instead of catching TrainNotFoundException, the code catches BusinessLogicException, to handle not only train not found exceptions but all kinds of business logic exceptions.
You might also want to add custom functionality. We built chained exceptions before the language supported it. On one project we saved the stack trace as a private String so it would be serialized across network calls where the normal stack trace info is "transient" and is discarded by serialize. Another project supported multiple levels of messages: a short one that appears on screen, a longer one that explains the problem, and the original technical message that is useful only to support folks. Probably too much, eh?
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi