Is it bad practice to throw multiple custom exceptions in Java?
No. It is good practice.
The only situation where multiple exceptions might be a (slightly) bad idea is if there is absolutely no possibility (ever!) of catching individual exceptions; i.e. the fine-grained exceptions won't serve any functional purpose. However, my opinion is that if you can make that assertion, then there is probably something wrong with the way that you / your team is using Java. And the counter-argument is that sensible use of multiple custom exceptions will help you to document the APIs ... even if you are never going to do more than catch-log-and-bail-out at runtime.
This is not to say that lots of custom exceptions will always be good:
If you go overboard and create a separate exception for everything, then you are probably adding unnecessary complexity. (In a lot of cases, different exception messages are sufficient.)
If you don't have a sensible inheritance hierarchy for your custom exceptions, then you may end up regretting it. (A well-designed hierarchy allows you to catch "classes" of exceptions, or declare methods as throwing them. It can make your code simpler.)
Is it bad practice to throw multiple custom exceptions in Java?
No. It is good practice.
The only situation where multiple exceptions might be a (slightly) bad idea is if there is absolutely no possibility (ever!) of catching individual exceptions; i.e. the fine-grained exceptions won't serve any functional purpose. However, my opinion is that if you can make that assertion, then there is probably something wrong with the way that you / your team is using Java. And the counter-argument is that sensible use of multiple custom exceptions will help you to document the APIs ... even if you are never going to do more than catch-log-and-bail-out at runtime.
This is not to say that lots of custom exceptions will always be good:
If you go overboard and create a separate exception for everything, then you are probably adding unnecessary complexity. (In a lot of cases, different exception messages are sufficient.)
If you don't have a sensible inheritance hierarchy for your custom exceptions, then you may end up regretting it. (A well-designed hierarchy allows you to catch "classes" of exceptions, or declare methods as throwing them. It can make your code simpler.)
Is it bad practice to throw multiple custom exceptions in Java?
Generally speaking: No. Why should it?
As with everything: Abstraction is your friend.
Is it necessarry to have a CustomerNotFound Exception and a ProductNotFound Exception? Or are your requirements just a more abstract NotFoundException?
The context could help to determine, what was missing. Having different exceptions for the sake of having them is nonsense.
Is it necessary, each layer of your application having custom exceptions? Exceptions are a way to report, that an intended action failed due to some reason.
Say, you have a controller which asks the service-layer to retrieve data, which in turn asks the DA-layer to read values from the DB. The resultset is empty. The service gets the empty resultset and throws a
NotFoundExceptionthe service communicates, the failure of the action due to a missing result.Say, the controller needs the service to do the payrolls for employees. And the service is asked to do the payroll for the employee with ID
123456, and in turn asks a service to retrieve the employee - but no emloyee could be found.
There are two ways to deal with that:
1) You throw a NotFound exception in the DA-Layer, catch it in the payroll-service and rethrow a PayrollServiceException wrapping the NotFoundException with the message Exmployee could not be found
2) You throw a NotFound exception in the DA-Layer and do not catch it in the payroll service and catch it instead a layer above.
I would go for (2), since in (1) the information, that the action failed because of a missing employee is redundant.
Videos
You should be able to create a custom exception class that extends the Exception class, for example:
class WordContainsException extends Exception
{
// Parameterless Constructor
public WordContainsException() {}
// Constructor that accepts a message
public WordContainsException(String message)
{
super(message);
}
}
Usage:
try
{
if(word.contains(" "))
{
throw new WordContainsException();
}
}
catch(WordContainsException ex)
{
// Process message however you would like
}
You need to create a class that extends from Exception. It should look like this:
public class MyOwnException extends Exception {
public MyOwnException () {
}
public MyOwnException (String message) {
super (message);
}
public MyOwnException (Throwable cause) {
super (cause);
}
public MyOwnException (String message, Throwable cause) {
super (message, cause);
}
}
Your question does not specify if this new exception should be checked or unchecked.
As you can see here, the two types are different:
Checked exceptions are meant to flag a problematic situation that should be handled by the developer who calls your method. It should be possible to recover from such an exception. A good example of this is a FileNotFoundException. Those exceptions are subclasses of Exception.
Unchecked exceptions are meant to represent a bug in your code, an unexpected situation that you might not be able to recover from. A NullPointerException is a classical example. Those exceptions are subclasses of RuntimeException
Checked exception must be handled by the calling method, either by catching it and acting accordingly, or by throwing it to the calling method. Unchecked exceptions are not meant to be caught, even though it is possible to do so.
In the spirit of the question as asked:
You would have to catch the various exceptions within your method, and then throw a CustomException from your catch block. The ability for an exception to "wrap" around another exception is built in via the Exception class itself (see the Exception(Throwable cause) constructor).
public void method() throws IOException, CustomException {
try {
//Body of the method
} catch (IllegalArgumentException | InstantiationException | IllegalAccessException e) {
throw new CustomException(e);
}
}
That said, IllegalArgumentException is not a checked exception, so you wouldn't have to declare it anyway.
Also worth pointing out, the above is based on you specifying that you want to create a custom exception. Another option is to declare in your throws clause some type that is a common base class of the various checked exceptions that might actually be thrown. For example, both of the checked exceptions in your list are subclasses of ReflectiveOperationException, so you could just say
public void method() throws IOException, ReflectiveOperationException {
//Body of the method
}
The trade-off, of course, is that you're not being as informative to those writing code that calls your method, so that may limit the quality of their exception handlers. In the extreme, you could just say throws Thorwable, but this is pretty poor form.
Declare a CustomException class that declares only constructors with these specific classes.
In this way it can only wrapped these exceptions and not any other.
public class CustomException extends RuntimeException{
public CustomException(IllegalArgumentException e) {
super(e);
}
public CustomException(IllegalAccessException e) {
super(e);
}
public CustomException(InstantiationException e) {
super(e);
}
}
Yes. There are two ways to do this:
Class hierarchies
This one only applies if you are the one designing the exceptions. If that doesn't describe this case, move on to the next chapter.
If you have, say, a user authentication API, you would presumably want to create a whole bevy of exceptions such as UserNotFoundException, IncorrectPasswordException, UserFrozenException, IpBlockedException, and more.
If you make sure all those exceptions extend a single exception type (AuthenticationException), like so:
public class AuthenticationException extends Exception {
public AuthenticationException(String msg, Throwable cause) {
super(msg, cause);
}
public AuthenticationException(String msg) {
super(msg);
}
}
public class UserNotFoundException extends AuthenticationException {
public UserNotFoundException(String username) {
super(username);
}
}
// and so on
then a caller can choose, which is why this makes for such a great API design.
IF a caller needs to have custom reactions depending on what kind of authentication problem occurs, they can catch, say, UserNotFoundException. But if they don't particularly care, they can catch AuthenticationException.
Note that java itself does this, too. GeneralSecurityException is the common superclass, and yet most security-related methods throw a sizable list of subclasses of this, so that callers know exactly what kind of errors can occur, and can write handlers for specific errors, without forcing them to write a ton of catch blocks if they don't want to.
rethrow
An alternate solution is that you bundle up exceptions into your own custom type.
To do this, first write an exception (or use an existing one, but that's rarely stylistically the right move). Then, write a catch block and wrap all those weird, unrelated exceptions into this newly created one, making sure to use the 'cause' system:
public class CustomException { // find a better name
public CustomException(String msg, Throwable cause) {
super(msg, cause);
}
public CustomException(String msg) {
super(msg);
}
public CustomException(Throwable cause) {
super(cause);
}
}
public void myMethod() throws CustomException {
try {
// code here
} catch (ApiException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
throw new CustomException(e);
} catch (InvocationTargetException e) {
throw new CustomException(e.getCause();
}
}
but note how your suggestion that you just want to fire-and-forget is causing your API design to be problematic. For example, wrapping an InvocationTargetException like this is rather hostile to your API consumers; InvocationTargetException is itself a wrapper, so now you've got wrappers-in-wrappers-in-wrappers and that's just ugly and makes it real hard for calling code to even try to deal with problems in a pinpoint fashion. There really is no easy way around reading the APIs you use and understanding why it throws the various exceptions that it throws.
NB: If you can, the class hierarchies solution is a much better way to do this; but it does require that you are in control of the code that's throwing them.
Suppose you have:
void myMethod() throws ApiException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
/// Your code here;
}
You can change it with:
void myMethod() throws CustomException {
try {
/// Your code here;
} catch (ApiException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new CustomException(e); // Make sure to have constructor initialized with cause.
}
}
E.g. CustomException class:
public class CustomException {
CustomException(Throwable cause) {
super(cause);
}
}