The advantage is that usually the caller has nothing to do with exception. He catches it, wraps it with another exception, and throws it again. Or, conversely, it throws exception using the throws keyword and becomes transparent to this type if the exception is thrown.
I would say that the described situation is typical for applications where we usually write business code and have one centralized place that handles all exceptions. This is not true for the API. For example, if you use a library that implements SSH, you expect it to throw an IOException (or even a more specialized exception) when something goes wrong.
source share