Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't we use RuntimeException instead of creating custom exceptions? [duplicate]

Tags:

java

exception

  1. I have been searching a lot on when exactly we should go creating custom exceptions. I found this example:

     public class IncorrectFileExtensionException extends Exception {
         public IncorrectFileExtensionException () {
    
         }
    
         public IncorrectFileExtensionException (String message) {
             super (message);
         }
    
         public IncorrectFileExtensionException (Throwable cause) {
             super (cause);
         }
    
         public IncorrectFileExtensionException (String message, Throwable cause) {
             super (message, cause);
         }
     }
    

    What's the real value in providing the above custom exception? Instead of creating the above custom exception, why can I not throw a new RuntimeException("error occurred", e)? I have seen many examples on the internet creating similar custom exceptions, but I don't understand what the real benefit in the above approach is.

    If we create something like IncorrectFileExtensionException, then our project ends up with many custom exceptions.

  2. I also found this:

     public class MyUncheckedBusinessException extends RuntimeException {
    
         private static final long serialVersionUID = -8460356990632230194L;
    
         private final ErrorCode code;
    
         public MyUncheckedBusinessException(ErrorCode code) {
             super();
             this.code = code;
         }
    
         public MyUncheckedBusinessException(String message, Throwable cause, ErrorCode code) {
             super(message, cause);
             this.code = code;
         }
    
         public MyUncheckedBusinessException(String message, ErrorCode code) {
             super(message);
             this.code = code;
         }
    
         public MyUncheckedBusinessException(Throwable cause, ErrorCode code) {
             super(cause);
             this.code = code;
         }
    
         public ErrorCode getCode() {
             return this.code;
         }
     }
    

    This is to some extent better than IncorrectFileExtensionException, as we are providing some error code at least. But again, what if all custom exceptions ends up like the above (I mean with an error code)?

    My question is: What's the best practice for custom exceptions? When exactly should we go for custom exceptions? Is IncorrectFileExtensionException really a good approach?

  3. When should we NOT create custom exceptions?

like image 622
john Avatar asked Oct 02 '19 07:10

john


4 Answers

public class MyBusinessRuntimeException extends RuntimeException {
    // copy all the constructors you need
}

It's a good practice because it helps to group and differentiate error types. You could claim "My API throws MyBusinessRuntimeException types" and abstract out other RuntimeException types you have no control over. It would tell the user what exception they are going to work with, and what exceptions they should consider as abnormalities.

IncorrectFileExtensionException shouldn't directly extend Exception. They are on completely different levels of abstraction.

Consider

 Exception
     FileException
         FileExtensionException
             IncorrectFileExtensionException
             UnsupportedFileExtensionException
like image 97
Andrew Tobilko Avatar answered Dec 04 '22 01:12

Andrew Tobilko


Other thing to consider is creating handler for the exceptions.

If you throw two following exceptions: new RuntimeException("User not found") and new RuntimeException("Event not created") how do you handle them? catching every runtime exception and then having if-else that compares messages?

That would be pain in the ass in long term. Same happens when you unit test logic that throws exceptions - you would again have to use if(ex.message.equals(someMessage)) just to have a unit test.

And then what happens when exception messages are the same for different business logic? Just operating with custom exceptions gives you so much ease on handling the flow - from making the catch hierarchy clear to creating some custom solutions that tells handlers how to behave (e.g. tell controller advice to throw 404)

like image 45
wizzle Avatar answered Dec 03 '22 23:12

wizzle


The reason custom exceptions are preferred is because they tell you exactly what's wrong. Having everything as a runtime exception makes it less of a hassle to throw exceptions, yes, but what if you had multiple pieces of code running consecutively that can each go wrong in their own way? There are cases where you'd want to handle each of these exceptions separately and with different logic.

This also allows for better testing in the future. If you would, for instance, want to test if your code runs properly you'd also want to test if your program throws the correct exceptions. By using separate classes you can quickly detect whether or not the correct logic was executed that resulted in that specific exception being thrown.

like image 35
martijn p Avatar answered Dec 04 '22 01:12

martijn p


According to the SEI CERT Oracle Coding Standard for Java throw RuntimeException, Exception, or Throwable is not a good practice. Therefore you never should throw an RuntimeException instead of a subclass.

Methods must not throw RuntimeException, Exception, or Throwable. Handling these exceptions requires catching RuntimeException, which is disallowed by ERR08-J. Do not catch NullPointerException or any of its ancestors. Moreover, throwing a RuntimeException can lead to subtle errors; for example, a caller cannot examine the exception to determine why it was thrown and consequently cannot attempt recovery. Methods can throw a specific exception subclassed from Exception or RuntimeException. Note that it is permissible to construct an exception class specifically for a single throw statement.

Regarding to your concern:

If we create like IncorrectFileExtensionException, then in our project ends up with many custom exceptions.

You should favor the use of Built-in exceptions available in Java libraries, this approach will help you to create less custom exceptions. According to Joshua Bloch in his awesome book Effective Java:

Reusing standard exceptions has several benefits. Chief among them is that it makes your API easier to learn and use because it matches the established conventions that programmers are already familiar with. A close second is that programs using your API are easier to read because they aren’t cluttered with unfamiliar exceptions. Last (and least), fewer exception classes means a smaller memory footprint and less time spent loading classes.

The most commonly reused exception type is IllegalArgumentException.

For example instead of create a IncorrectFileExtensionException class you could throw an IllegalArgumentException with a well written error message.

...
String message = String.format("'%s' is an incorrect file extension.", fileExtension);
throw new IllegalArgumentException(message);
...

Therefore you should create a custom exception when you can't reuse a built-in one.

like image 26
eHayik Avatar answered Dec 04 '22 01:12

eHayik