3

I am taking a Java course. So I am just learning Java. The textbook says to either extend the Exception class or extend the RuntimeException class for a custom exception. I understand RuntimeException is a subclass of Exception.

I have a homework assignment to implement the bin2Dec method to throw a custom exception if the string is not a binary string.

I found the exercise worked out by somebody and was studying their solution. However, I see that they extended the NumberFormatException class which of course is a child of IllegalArgumentException which is a child of RuntimeException.

This led me to wonder why they decided to use NumberFormatException? I assume I can work out a solution simply using Exception or RuntimeException. Especially since that is all that is covered in the text.

I tried searching the web to find answers to this question but all I found was several places stating basically what the book says (extend Exception or RuntimeException) and explaining (as the book does) when to use one vs the other.

All I was able to find was several articles saying that you "can" use a more appropriate subclass like NumberFormatException but no explanation of how a person would come to that conclusion when setting out to make a custom exception. I found one article saying extending NumberFormatException is almost always a bad idea and explained several reasons why but then it said IllegalArgumentException would likely be more appropriate. This leaves me wondering the same question... What would lead me to decide to use IllegalArgumentException instead of Exception or RuntimeException.

5
  • 2
    Descendants of RuntimeException usually indicate programmer mistakes, which is why the compiler does not require calling code to catch such an exception: it should halt execution of the thread, so that programmers are motivated to fix the mistake. All other exception types must be caught by calling code. So, you will need to ask yourself: if my exception is thrown, is it because a programmer made a mistake, or is it because the exception represents a condition caused by something outside of the programmer’s control (like user input) which the program must be prepared to deal with?
    – VGR
    Commented Feb 12 at 20:21
  • I think your comment is referring to how to decide between "extends Exception" or "extends RuntimeException." Correct? If so... Like I said, I have found lots of explanations on that. The book also explains this. However, my question is... Should I ever use one of the other subclasses? For example "extends NumberFormatException"? If yes... How would I come to that conclusion?
    – XCELLGUY
    Commented Feb 12 at 20:26
  • 3
    The same way one would decide whether to extend any class: is your exception truly indicating that an input string did not conform to Java code's number syntax? Subclassing should be done where one really wants to make a specialized type which can act as a stand-in for instances of the superclass. If your exception does not conform to the contract of NumberFormatException as described in that class’s documentation, you probably should not extend NumberFormatException.
    – VGR
    Commented Feb 12 at 20:33
  • 2
    By the way, if this bin2Dec method is supposed to return an int, then its wrongly named. There is nothing decimal about an int. An int is just a bit pattern. The "decimal" is just a string representation. If the method really means "binary to decimal" then it should return a decimal String.
    – k314159
    Commented Feb 12 at 21:11
  • "I found one article saying extending NumberFormatException is almost always a bad idea" - what reasons did it give?
    – k314159
    Commented Feb 14 at 13:02

3 Answers 3

4

This led me to wonder why they decided to use "NumberFormatException"?

NumberFormatException is a very clear Exception; it says that the String (or other object) that the program tried to convert to a number wasn't in a format that the Method could read. With this information, the programmer can go to the Javadocs to learn more about their misunderstanding of what the input to the method that generated this exception should look like. So in your case using NumberFormatException or subclassing it and using that subclass seems like it would be very appropriate for a function that converts a binary number to a decimal number.

In terms of the bigger picture:

  1. subclassing from RuntimeException is often the best way to go (IMO). I like the "fast fail" paradigm: Fail, and describe the failure reason. The client user has the option of running again and fixing the input... or just not. I prefer not to loop and ask the user for input repeatedly until its valid, and I think this can be annoying. A good non-RuntimeException example is IOException and its subclass SocketException. Sockets (and SocketExceptions) are a regular part of cross-computer communication, and a SocketException on a port that is listening for input lets the programmer know that the Socket has been closed, and releases the Socket and the Thread waiting on it.
  2. FYI There is a 3rd kind of Throwable, which is Error. When you have time you should read about what makes an Error an Error.
  3. Java and the Java console in particular make input validation more complicated than it can otherwise be. The state of the art on this right now (IMO) is HTML 5, where you can specify both the type of an INPUT (like number, url, etc) and/or a Regular Expression pattern that the input must follow. Using these, the web browser will stop the user from submitting a form if the input is not valid.

--Edit--

Honza Zidek below has a good point that even if you validate a submission using HTML5, you still need to check the validation on the server(Java) side

2
  • "Using these, the web browser will stop the user from submitting a form if the input is not valid." This is good recommendation which I agree with, however your advice might easily be misinterpreted that the validation can be moved to frontend, which is a crucial error in design. I am sure you didn't mean it, but still I would recommend you to add this to your point nr. 3. Commented Feb 17 at 10:58
  • @HonzaZidek Good point Commented Feb 17 at 12:49
1

In real life applications, all you usually need to distinguish is "Client Error" vs. "System Error":

Error Meaning Corresponding HTTP code
Client Your client provided invalid input,
repeating the action will also fail,
it's the client who should fix it.
4xx
System Your application has an error,
client might try again later
or they should call your helpdesk.
5xx

There are no other types of errors on this level of abstraction.

Eventually, all your Java exceptions must end up mapped into one of these two categories.

There are many people who speak against the checked exceptions (those extending Exception and not RunTimeException). Both C#, which is something like Java++, as well as Kotlin, which is something like Java+++ :), decided to get rid of the checked exceptions totally.

You may read for example these:

In our production backend Java applications, we usually catch the checked exception as low as possible and immediately map them into our own runtime exception, which is then caught at the top-level in the controller and mapped into the proper HTTP or GraphQL error.

Because your task is a homework assignment and your instructions are "to implement a method to throw a custom exception", apparently they want you to understand how to create a custom exception and how to handle it. Just do what they ask you for and do not worry too much :)

In real life, just throw the exception which is the closest to your use case.

The rule of thumb is that:

  • any suitable runtime exception, if the exceptional situation is unexpected, it is the violation of the contract of your method, such as: the method contract says only a valid string is expected, but the client (= another code calling your method) provided an invalid string
  • any suitable checked exception, if you really wish the client to bother to test the success of the call
  • whichever you decide, fail fast, which means do not continue with execution and let your code flow fail as soon as something goes wrong - do not let the error stay masked for long time to materialize later as some mysterious NullPointerException :)

You may also ready my other answer https://stackoverflow.com/a/36309228/2886891 with simplified explanation of exceptions in Java.

0

-> Extend Exception for checked exceptions (must be declared in method signatures). -> Extend RuntimeException for unchecked exceptions (optional handling, usually due to programmer error). -> NumberFormatException is a subclass of IllegalArgumentException and is thrown when a string does not match the expected numerical format. -> IllegalArgumentException is for bad method arguments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.