One reason is for performance. Throwing and catching an exception is cheap; the expensive part is filling in the stack trace. If you override fillInStackTrace()
to do nothing, creating an exception also becomes cheap.
With cheap exceptions, you can use exceptions for flow control, which can make the code more readable in certain situations; you can use them when when implementing JVM languages where you need more advanced flow control, and they are useful if you are writing an actors library.