Instead of handling exceptions in our code and then calling sendError(), we can define error pages in the deployment descriptor and then the rest of the headache is handled by the container after making the required mapping for the exception classes and the corresponding error codes. Then, why should one ever use the first approach to handle the exception?
You use reponse.sendError to send a particular HTTP status code to the client. In particular, you can send a 404 status code along with a Web page explaining why the page could not be found (e.g., that the request failed to provide the information needed to do a redirect, or some such).
You can indeed use error-page and error-code in web.xml to create Web-application-wide 404 pages. This is most definitely a good idea, but is different than using response.sendError for a page-specific 404 error page.
However, IMHO the idea of using error-page and exception-type to provide error pages for uncaught Java exceptions is not a very good one. There are two reasons why I am very dubious about this idea except as a warning for developers (eg for NullPointException) during initial development: