The use of exception handling does not spare you the effort of doing the work of detecting, reporting, and handling errors. Sometimes it is desirable to propagate exception handling up the call stack and let the corrective action be taken at a higher level. For example, you might provide a class with methods which implements a stack data structure. One of the methods of your class might be to pop an element off the stack. That decision might best be left to the user of your stack class and you might simply propagate the notification up to the calling method and let that method take the corrective action.
Objects are instances of classes.
Classes may be inherited in Java. As a result of the above, a natural hierarchy can be created which causes exceptions to be grouped in logical ways. For example, going back to the stack example, you might create an exception class which applies to all exceptional conditions associated with an object of your stack class. From this, you might inherit other classes which pertain to specific exceptional conditions such a push exceptions, pop exceptions, initialization exceptions, etc. If your code throws an exception object of one of the specific types, that object can be caught either by an exception event handler designed to catch on the basis of the group of exceptions, or one designed to catch on the basis of one of the specialized exceptions.