Java Type of Exception to Throw - java

I am trying to understand WHY to throw certain exceptions. What does it matter which one I choose to throw?
For example
//simple division method - a/b
public static double divide(double a, double b){
if(b == 0)
throw new IllegalArgumentException("b = 0");
return a/b;
}
vs
//simple division method - a/b
public static double divide(double a, double b){
if(b == 0)
throw new IllegalArithmeticException("b = 0");
return a/b;
}
(Apologies if there are errors in the code - I threw it together quickly. I'm not actually interested in the method itself.)
Does it matter which exception I choose? It seems like it could be anything - even if I used arrayIndexOutOfBoundsException, it would still stop the program and print what I want it to print.
Thanks for any help.

It's worth discussing what the difference is between a checked and an unchecked exception is, to hammer home a critical point of what exception to throw.
Let's say that you're attempting to read a file, and for whatever reason, the file isn't found. Java has a convenient FileNotFoundException that you can use to explicitly inform that the file isn't found. It's also one of the exceptions which extend (through its hierarchy) Exception, meaning that if a method states that this exception is thrown, it must be dealt with either by catching it or declaring it to be thrown elsewhere.
Then, there's the ArithmeticException, which is a runtime exception (it extends RuntimeException) - no methods need to declare this to be thrown, and you're not required to catch it explicitly, since this class of exceptions indicate an error in the code. It can come up, and in actuality, if anything were to try and catch a runtime exception, it'd look a little bit suspect.
In the context of your problem, you're basically stomping over the natural throwing of the ArithmeticException by forewarning the user of valid input. It's likely acceptable to do something like this, but for this context, you actually don't need to throw anything yourself. If someone decides to pass b = 0 into the method, they'll get the ArithmeticException.
There are existing conventions to follow based on exceptions - be as specific about the problem as possible, and offer a way to recover if appropriate - so in this scenario, if you had to throw a specific exception, I'd recommend IllegalArgumentException, since the argument b = 0 isn't acceptable when dividing or doing modulo. However, I'd also recommend that it be caught in a method outside of this instead, since the input is really suspect and it should be ideally sanitized before it makes its way to this method.

Well, from a company's point of view, it does matter what exception you're throwing. Because tecnically, you create programs for the users to work on it and if the user enters undesirable input then he/she will be able to get what mistake he/she has made.
It works as a note for the user to correct the mistakes.

Related

Java pattern for interfaces and RuntimeExceptions

I am using the following pattern in a project of mine.
public interface Foo {
// When given a positive number, double it
public Integer doublePositiveNumber(int number);
}
public class FooImpl {
public Integer doublePositiveNumber(int number) {
if (number < 0) {
throw new IllegalArgumentException("number must be positive")
}
return number * 2;
}
}
There is one main thing that has been bothering me about this design. It's not clear to anyone using this implementation of the interface that they may need to handle an IllegalArgumentException. Likewise, I want other implementations of this interface to throw this exception if a negative number is passed in.
I've thought about a few approaches to solving this:
1) Do nothing, this pattern is fine and normal
2) Throw a custom checked exception instead. This feels awkward since IllegalArgumentException is perfect for this error.
3) Add "throws IllegalArgumentException" to the method signature. The java code-quality scanner I am using on my project claims that throwing a RuntimeException in the signature like this is a code smell and should be avoided.
I was hoping someone could shed some light on if there is a good pattern for what I am looking to do. I can't tell if I am over-engineering things or thinking about this situation correctly.
I'd make your own checked exception - something like "NegativeNumberException", since that describes what caused this error.
RuntimeErrors like IllegalArgumentException are generally intended to be thrown in case of programmer error - if you're expecting it to be caught, then you should use a checked one.
You can always add a Javadoc connect with an #throws annotation, but it's better, from what you're describing, to have the compiler barf when a caller fails to handle the exception.

Is using IllegalArgumentException correct if field is wrong? [duplicate]

I'm worried that this is a runtime exception so it should probably be used sparingly.
Standard use case:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
But that seems like it would force the following design:
public void computeScore() throws MyPackageException {
try {
setPercentage(userInputPercent);
}
catch(IllegalArgumentException exc){
throw new MyPackageException(exc);
}
}
To get it back to being a checked exception.
Okay, but let's go with that. If you give bad input, you get a runtime error. So firstly that's actually a fairly difficult policy to implement uniformly, because you could have to do the very opposite conversion:
public void scanEmail(String emailStr, InputStream mime) {
try {
EmailAddress parsedAddress = EmailUtil.parse(emailStr);
}
catch(ParseException exc){
throw new IllegalArgumentException("bad email", exc);
}
}
And worse - while checking 0 <= pct && pct <= 100 the client code could be expected to do statically, this is not so for more advanced data such as an email address, or worse, something that has to be checked against a database, therefore in general client code cannot pre-validate.
So basically what I'm saying is I don't see a meaningful consistent policy for the use of IllegalArgumentException. It seems it should not be used and we should stick to our own checked exceptions. What is a good use case to throw this?
The API doc for IllegalArgumentException:
Thrown to indicate that a method has been passed an illegal or inappropriate argument.
From looking at how it is used in the JDK libraries, I would say:
It seems like a defensive measure to complain about obviously bad input before the input can get into the works and cause something to fail halfway through with a nonsensical error message.
It's used for cases where it would be too annoying to throw a checked exception (although it makes an appearance in the java.lang.reflect code, where concern about ridiculous levels of checked-exception-throwing is not otherwise apparent).
I would use IllegalArgumentException to do last ditch defensive argument checking for common utilities (trying to stay consistent with the JDK usage). Or where the expectation is that a bad argument is a programmer error, similar to an NullPointerException. I wouldn't use it to implement validation in business code. I certainly wouldn't use it for the email example.
When talking about "bad input", you should consider where the input is coming from.
Is the input entered by a user or another external system you don't control, you should expect the input to be invalid, and always validate it. It's perfectly ok to throw a checked exception in this case. Your application should 'recover' from this exception by providing an error message to the user.
If the input originates from your own system, e.g. your database, or some other parts of your application, you should be able to rely on it to be valid (it should have been validated before it got there). In this case it's perfectly ok to throw an unchecked exception like an IllegalArgumentException, which should not be caught (in general you should never catch unchecked exceptions). It is a programmer's error that the invalid value got there in the first place ;) You need to fix it.
Throwing runtime exceptions "sparingly" isn't really a good policy -- Effective Java recommends that you use checked exceptions when the caller can reasonably be expected to recover. (Programmer error is a specific example: if a particular case indicates programmer error, then you should throw an unchecked exception; you want the programmer to have a stack trace of where the logic problem occurred, not to try to handle it yourself.)
If there's no hope of recovery, then feel free to use unchecked exceptions; there's no point in catching them, so that's perfectly fine.
It's not 100% clear from your example which case this example is in your code, though.
Treat IllegalArgumentException as a preconditions check, and consider the design principle: A public method should both know and publicly document its own preconditions.
I would agree this example is correct:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
If EmailUtil is opaque, meaning there's some reason the preconditions cannot be described to the end-user, then a checked exception is correct. The second version, corrected for this design:
import com.someoneelse.EmailUtil;
public void scanEmail(String emailStr, InputStream mime) throws ParseException {
EmailAddress parsedAddress = EmailUtil.parseAddress(emailStr);
}
If EmailUtil is transparent, for instance maybe it's a private method owned by the class under question, IllegalArgumentException is correct if and only if its preconditions can be described in the function documentation. This is a correct version as well:
/** #param String email An email with an address in the form abc#xyz.com
* with no nested comments, periods or other nonsense.
*/
public String scanEmail(String email)
if (!addressIsProperlyFormatted(email)) {
throw new IllegalArgumentException("invalid address");
}
return parseEmail(emailAddr);
}
private String parseEmail(String emailS) {
// Assumes email is valid
boolean parsesJustFine = true;
// Parse logic
if (!parsesJustFine) {
// As a private method it is an internal error if address is improperly
// formatted. This is an internal error to the class implementation.
throw new AssertError("Internal error");
}
}
This design could go either way.
If preconditions are expensive to describe, or if the class is intended to be used by clients who don't know whether their emails are valid, then use ParseException. The top level method here is named scanEmail which hints the end user intends to send unstudied email through so this is likely correct.
If preconditions can be described in function documentation, and the class does not intent for invalid input and therefore programmer error is indicated, use IllegalArgumentException. Although not "checked" the "check" moves to the Javadoc documenting the function, which the client is expected to adhere to. IllegalArgumentException where the client can't tell their argument is illegal beforehand is wrong.
A note on IllegalStateException: This means "this object's internal state (private instance variables) is not able to perform this action." The end user cannot see private state so loosely speaking it takes precedence over IllegalArgumentException in the case where the client call has no way to know the object's state is inconsistent. I don't have a good explanation when it's preferred over checked exceptions, although things like initializing twice, or losing a database connection that isn't recovered, are examples.
As specified in oracle official tutorial , it states that:
If a client can reasonably be expected to recover from an exception,
make it a checked exception. If a client cannot do anything to recover
from the exception, make it an unchecked exception.
If I have an Application interacting with database using JDBC , And I have a method that takes the argument as the int item and double price. The price for corresponding item is read from database table. I simply multiply the total number of item purchased with the price value and return the result. Although I am always sure at my end(Application end) that price field value in the table could never be negative .But what if the price value comes out negative? It shows that there is a serious issue with the database side. Perhaps wrong price entry by the operator. This is the kind of issue that the other part of application calling that method can't anticipate and can't recover from it. It is a BUG in your database. So , and IllegalArguementException() should be thrown in this case which would state that the price can't be negative.
I hope that I have expressed my point clearly..
Any API should check the validity of the every parameter of any public method before executing it:
void setPercentage(int pct, AnObject object) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("pct has an invalid value");
}
if (object == null) {
throw new IllegalArgumentException("object is null");
}
}
They represent 99.9% of the times errors in the application because it is asking for impossible operations so in the end they are bugs that should crash the application (so it is a non recoverable error).
In this case and following the approach of fail fast you should let the application finish to avoid corrupting the application state.

Throwing an IllegalArgumentException isn't working

So, for a homework assignment, our professor wants us to try inserting an integer into an array of Strings:
public boolean addPerson(V person, int number)throws IllegalArgumentException{
if(numEntries < people.length){
people[numEntries] = person;
phones[numEntries] = number;
numEntries++;
return true;
}
return false;
}
public static void main(String[] args){
PhoneBook<String> names = new PhoneBook<String>();
PhoneBook<Integer> ssn = new PhoneBook<Integer>();
names.addPerson("john", 1235681213);
ssn.addPerson(123324567, 2048);
Integer soc = 132546789;
try{
names.addPerson(soc, 1996);
}
catch(IllegalArgumentException e){
System.out.println("You cannot enter a Social Security Number "
+ "into the Name phone book!");
}
But, this isn't working, and I still get the same error as without the try-catch. Any idea what I'm doing wrong?
EDIT
Sorry guys, I probably should've included the code for the addPerson method. I don't really know how to deal with exceptions yet.
What your professor likely wants you to observe is a compilation error. An array's type is fixed at instantation time, and will not change. The array will only ever accept whatever type it has been declared to accept, and nothing else.
Minor rant about exceptions to follow from here.
Let's have a quick chat about checked and unchecked exceptions. There is a difference between these two, and mixing them up can be painful at times.
Let's start with the checked exceptions. These are the exceptions that you must either explicitly catch yourself, or declare them to be thrown. Things along those lines are IOException, FileNotFoundException*, and a few others - pretty much anything that extends from the Exception class.
Java is telling you that you have the ability to recover from this error, and you as a good developer should ensure that your program does.
There are also unchecked exceptions; anything that extends RuntimeException or Error. These do not need to be declared to be thrown, as they occur during the runtime of the application, and there's really no guarantee if the program should recover from this error. An example of this would be ArithmeticException; should your application really recover if it tried to divide by zero? What state would it be in?
There are also some you really shouldn't be catching at all - what would you return to if you managed to catch an OutOfMemoryError? There isn't much you really can do at that point!
Now, to your code: you've declared an unchecked exception to be thrown. That's valid syntax, but Java isn't going to just arbitrarily throw the exception for you, because there isn't anything in that block of code that would just throw it. At worst, you could get an ArrayIndexOutOfBoundsException, but that's no IllegalArgumentException.
In order to actually throw that unchecked exception, you'd need to explicitly throw it:
throw new IllegalArgumentException();
...and you'd also need a good reason to do so. Exceptions are expensive.
*: I realize that FileNotFoundException is-an IOException. It's still checked.

True-way solution in Java: parse 2 numbers from 2 strings and then return their sum

Given the code:
public static int sum(String a, String b) /* throws? WHAT? */ {
int x = Integer.parseInt(a); // throws NumberFormatException
int y = Integer.parseInt(b); // throws NumberFormatException
return x + y;
}
Could you tell if it's good Java or not? What I'm talking about is, NumberFormatException is an unchecked exception. You don't have to specify it as part of sum() signature. Moreover, as far as I understand, the idea of unchecked exceptions is just to signal that program's implementation is incorrect, and even more, catching unchecked exceptions is a bad idea, since it's like fixing bad program at runtime.
Would somebody please clarify whether:
I should specify NumberFormatException as a part of method's signature.
I should define my own checked exception (BadDataException), handle NumberFormatException inside the method and re-throw it as BadDataException.
I should define my own checked exception (BadDataException), validate both strings some way like regular expressions and throw my BadDataException if it doesn't match.
Your idea?
Update:
Imagine, it's not an open-source framework, that you should use for some reason. You look at method's signature and think - "OK, it never throws". Then, some day, you got an exception. Is it normal?
Update 2:
There are some comments saying my sum(String, String) is a bad design. I do absolutely agree, but for those who believe that original problem would just never appear if we had good design, here's an extra question:
The problem definition is like this: you have a data source where numbers are stored as Strings. This source may be XML file, web page, desktop window with 2 edit boxes, whatever.
Your goal is to implement the logic that takes these 2 Strings, converts them to ints and displays message box saying "the sum is xxx".
No matter what's the approach you use to design/implement this, you'll have these 2 points of inner functionality:
A place where you convert String to int
A place where you add 2 ints
The primary question of my original post is:
Integer.parseInt() expects correct string to be passed. Whenever you pass a bad string, it means that your program is incorrect (not "your user is an idiot"). You need to implement the piece of code where on one hand you have Integer.parseInt() with MUST semantics and on the other hand you need to be OK with the cases when input is incorrect - SHOULD semantics.
So, briefly: how do I implement SHOULD semantics if I only have MUST libraries.
In my opinion it would be preferable to handle exception logic as far up as possible. Hence I would prefer the signature
public static int sum(int a, int b);
With your method signature I would not change anything. Either you are
Programmatically using incorrect values, where you instead could validate your producer algorithm
or sending values from e.g., user input, in which case that module should perform the validation
Hence, exception handling in this case becomes a documentation issue.
This is a good question. I wish more people would think about such things.
IMHO, throwing unchecked exceptions is acceptable if you've been passed rubbish parameters.
Generally speaking, you shouldn't throw BadDataException because you shouldn't use Exceptions to control program flow. Exceptions are for the exceptional. Callers to your method can know before they call it if their strings are numbers or not, so passing rubbish in is avoidable and therefore can be considered a programming error, which means it's OK to throw unchecked exceptions.
Regarding declaring throws NumberFormatException - this is not that useful, because few will notice due to NumberFormatException being unchecked. However, IDE's can make use of it and offer to wrap in try/catch correctly. A good option is to use javadoc as well, eg:
/**
* Adds two string numbers
* #param a
* #param b
* #return
* #throws NumberFormatException if either of a or b is not an integer
*/
public static int sum(String a, String b) throws NumberFormatException {
int x = Integer.parseInt(a);
int y = Integer.parseInt(b);
return x + y;
}
EDITED:
The commenters have made valid points. You need to consider how this will be used and the overall design of your app.
If the method will be used all over the place, and it's important that all callers handle problems, the declare the method as throwing a checked exception (forcing callers to deal with problems), but cluttering the code with try/catch blocks.
If on the other hand we are using this method with data we trust, then declare it as above, because it is not expected to ever explode and you avoid the code clutter of essentially unnecessary try/catch blocks.
Number 4. As given, this method should not take strings as parameters it should take integers. In which case (since java wraps instead of overflowing) there's no possibility of an exception.
x = sum(Integer.parseInt(a), Integer.parseInt(b))
is a lot clearer as to what is meant than
x = sum(a, b)
You want the exception to happen as close to the source (input) as possible.
As to options 1-3, you don't define an exception because you expect your callers to assume that otherwise your code can't fail, you define an exception to define what happens under known failure conditions WHICH ARE UNIQUE TO YOUR METHOD. I.e. if you have a method that is a wrapper around another object, and it throws an exception then pass it along. Only if the exception is unique to your method should you throw a custom exception (frex, in your example, if sum was supposed to only return positive results, then checking for that and throwing an exception would be appropriate, if on the other hand java threw an overflow exception instead of wrapping, then you would pass that along, not define it in your signature, rename it, or eat it).
Update in response to update of the question:
So, briefly: how do I implement SHOULD semantics if I only have MUST libraries.
The solution to this is to to wrap the MUST library, and return a SHOULD value. In this case, a function that returns an Integer. Write a function that takes a string and returns an Integer object -- either it works, or it returns null (like guava's Ints.tryParse). Do your validation seperate from your operation, your operation should take ints. Whether your operation gets called with default values when you have invalid input, or you do something else, will depend upon your specs -- most I can say about that, is that it's really unlikely that the place to make that decision is in the operation method.
1. I should specify NumberFormatException as a part of method's signature.
I think so. It's a nice documentation.
2. I should define my own checked exception (BadDataException), handle NumberFormatException inside the method and re-throw it as BadDataException.
Sometimes yes. The checked exceptions are consider to be better in some cases, but working with them is quite a PITA. That's why many frameworks (e.g., Hibernate) use runtime exceptions only.
3. I should define my own checked exception (BadDataException), validate both strings some way like regular expressions and throw my BadDataException if it doesn't match.
Never. More work, less speed (unless you expect throwing the exception to be a rule), and no gain at all.
4. Your idea?
None at all.
Nr 4.
I think I wouldn't change the method at all.
I would put a try catch around the calling method or higher in the stack-trace where I'm in a context where I can gracefully recover with business logic from the exception.
I wouldn't certainty do #3 as I deem it overkill.
Assuming that what you are writing is going to be consumed (like as an API) by someone else, then you should go with 1, NumberFormatException is specifically for the purpose of communicating such exceptions and should be used.
First you need to ask your self, does the user of my method needs to worry about entering wrong data, or is it expected of him to enter proper data (in this case String).
This expectation is also know as design by contract.
and 3. Yes you probably should define BadDataException or even better use some of the excising ones like NumberFormatException but rather the leaving the standard message to be show. Catch NumberFormatException in the method and re-throw it with your message, not forgetting to include the original stack trace.
It depends on the situation bu I would probably go with re-throwing NumberFormatException with some additional info. And also there must be a javadoc explanation of what are the expected values for String a, String b
Depends a lot on the scenario you are in.
Case 1. Its always you who debug the code and no one else and exception wont cause a bad user experience
Throw the default NumberFormatException
Case2: Code should be extremely maintainable and understandable
Define your own exception and add lot more data for debugging while throwing it.
You dont need regex checks as, its gonna go to exception on bad input anyway.
If it was a production level code, my idea would be to define more than one custom exceptions, like
Number format exception
Overflow exception
Null exception etc...
and deal with all these seperately
You may do so, to make it clear that this can happen for incorrect input. It might help someone using your code to remember handling this situation. More specifically, you're making it clear that you don't handle it in the code yourself, or return some specific value instead. Of course, the JavaDoc should make this clear too.
Only if you want to force the caller to deal with a checked exception.
That seems like overkill. Rely on the parsing to detect bad input.
Overal, a NumberFormaException is unchecked because it is expected that correctly parseable input is provided. Input validation is something you should handle. However, actually parsing the input is the easiest way to do this. You could simply leave your method as it is and warn in the documentation that correct input is expected and anyone calling your function should validate both inputs before using it.
Any exceptional behaviour should be clarified in the documentation. Either it should state that this method returns a special value in case the of failure (like null, by changing the return type to Integer) or case 1 should be used. Having it explicit in the method's signature lets the user ignore it if he ensures correct strings by other means, but it still is obvious that the method doesn't handle this kind of failure by itself.
Answer to your updated question.
Yes it's perfectly normal to get "surprise" exceptions.
Think about all the run time errors one got when new to programming.
e.g ArrayIndexOutofBound
Also a common surprise exception from the for each loop.
ConcurrentModificationException or something like that
While I agree with the answer that the runtime exception should be allowed to be percolated, from a design and usability perspective, it would be a good idea to wrap it into a IllegalArgumentException rather than throw it as NumberFormatException. This then makes the contract of your method more clear whereby it declares an illegal argument was passed to it due to which it threw an exception.
Regarding the update to the question "Imagine, it's not an open-source framework, that you should use for some reason. You look at method's signature and think - "OK, it never throws". Then, some day, you got an exception. Is it normal?" the javadoc of your method should always spill out the behavior of your method (pre and post constraints). Think on the lines of say collection interfaces where in if a null is not allowed the javadoc says that a null pointer exception will be thrown although it is never part of the method signature.
As you are talking about good java practice ,in my opinion it is always better
To handle the unchecked exception then analyze it and through a custom unchecked exception.
Also while throwing custom unchecked exception you can add the Exception message that your client could understand and also print the stack trace of original exception
No need to declare custom exception as "throws" as it is unchecked one.
This way you are not violating the use of what unchecked exceptions are made for, at the same time client of the code would easily understand the reason and solution for the exception .
Also documenting properly in java-doc is a good practice and helps a lot.
I think it depends on your purpose, but I would document it at a minimum:
/**
* #return the sum (as an int) of the two strings
* #throws NumberFormatException if either string can't be converted to an Integer
*/
public static int sum(String a, String b)
int x = Integer.parseInt(a);
int y = Integer.parseInt(b);
return x + y;
}
Or, take a page from the Java source code for the java.lang.Integer class:
public static int parseInt(java.lang.String string) throws java.lang.NumberFormatException;
How about the input validation pattern implemented by Google's 'Guava' library or Apache's 'Validator' library (comparison)?
In my experience, it is considered good practice to validate a function's parameters at the beginning of the function and throw Exceptions where appropriate.
Also, I would consider this question to be largely language independent. The 'good practice' here would apply to all languages that have functions which can take parameters which may or may not be valid.
I think your very first sentence of "Quite a stupid question" is very relevant. Why would you ever write a method with that signature in the first place? Does it even make sense to sum two strings? If the calling method wants to sum two strings, it is the calling method's responsibility to make sure they are valid ints and to convert them before calling the method.
In this example, if the calling method cannot convert the two Strings into an int, it could do several things. It really depends at what layer this summation occurs at. I am assuming the String conversion would be very close to front-end code (if it was done properly), such that case 1. would be the most likely:
Set an error message and stop processing or redirect to an error page
Return false (ie, it would put the sum into some other object and would not be required to return it)
Throw some BadDataException as you are suggesting, but unless the summation of these two numbers is very important, this is overkill, and like mentioned above, this is probably bad design since it implies that the conversion is being done in the wrong place
There are lots of interesting answers to this question. But I still want to add this :
For string parsing, I always prefer to use "regular expressions". The java.util.regex package is there to help us. So I will end up with something like this, that never throws any exception. It's up to me to return a special value if I want to catch some error :
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public static int sum(String a, String b) {
final String REGEX = "\\d"; // a single digit
Pattern pattern = Pattern.compile(REGEX);
Matcher matcher = pattern.matcher(a);
if (matcher.find()) { x = Integer.matcher.group(); }
Matcher matcher = pattern.matcher(b);
if (matcher.find()) { y = Integer.matcher.group(); }
return x + y;
}
As one can see, the code is just a bit longer, but we can handle what we want (and set default values for x and y, control what happens with else clauses, etc...)
We could even write a more general transformation routine, to which we can pass strings, defaut return values, REGEX code to compile, error messages to throw, ...
Hope It was usefull.
Warning : I was not able to test this code, so please excuse eventual syntax problems.
You face this issue because you let user errors propagate too deep into the core of the application and partly also because you abuse Java data types.
You should have a clearer separation between user input validation and business logic, use proper data typing, and this problem will disappear by itself.
The fact is the semantics of Integer.parseInt() are known - it's primary purpose it to parse valid integers. You're missing an explicit user input validation/parsing step.

Java unchecked/checked exception clarification

I've been reading about unchecked versus checked questions, none of the online resources have been truly clear about the difference and when to use both.
From what I understand, both of them get thrown at runtime, both of them represent program states that are outside the expected bounds of the logic, but checked exceptions must be explicitly caught while unchecked ones do not.
My question is, suppose for argument's sake I have a method that divides two numbers
double divide(double numerator, double denominator)
{ return numerator / denominator; }
and a method that requires divison somewhere
void foo()
{ double a = divide(b, c); }
Who is responsible for checking the case of the denominator being zero, and should an exception be checked or unchecked (ignoring Java's built in divison checks)?
So, would the divide method be declared as is or as
double divide(double numerator, double denominator) throws DivideByZeroException
{
if(denominator == 0) throw DivideByZeroException
else ...
}
void foo()
{
try{
double a = divide(b, c);
}
catch(DivideByZeroException e)
{}
}
or without a checked exception, as is:
double divide(double numerator, double denominator)
{
if(denominator == 0) throw DivideByZeroException
else ...
}
void foo()
{
if(c != 0)
double a = divide(b, c);
}
and allow foo to make the divide by zero check?
This problem originally arose in a mathematical program I wrote in which users entered numbers and logic classes performed calculations. I was never sure whether the GUI should check immediately for improper values, or whether the internal logic should catch them during calculation and throw exceptions.
Interesting topic indeed!
After reading and trying lots of way to deal with errors in general and exceptions specifically I learned to differ between programmer errors and a expected errors.
Programmer errors should never be caught, but rather crash (!) early and hard. A programmer error is due to a logical fault, and the root cause should be fixed.
Expected errors should always be caught. Also when a expected error is caught a message must be displayed for the user. This has an important implication - If a expected error should not display an error, it's better to check whether the method will throw instead of letting it throw.
So applied to your example I would think "How should this look to the user?"
If a error-message should be displayed (in the browser output, console, messagebox) I would throw an exception and catch it as close to the UI as possible and output the error-message.
If no error message should be displayed I would check the input and not throw.
On a sidenote: I never throw DivideByZeroException nor NullPointerException - I let the JVM throw those for me. In this case you could brew your own exception-class or use a suitable built-in checked exception.
My favorite discussion on the difference in philosophy between checked and unchecked exceptions in Java:
http://www.javapractices.com/topic/TopicAction.do?Id=129
Assume that a checked exception is thrown as a result of a mathematical operation. E.g division (as per your post).
This would mean that every integer division should appear in a try block!
Actually division can throw an ArithmeticException which is unchecked exception so there is no need to catch it.
Actually you should not catch it, since it is an exceptional condition that occured and usually can only be solved by code correction.
In your case your code should have done something prior to actually divide by zero.
If you have reached the step where you allow to actually do the division by zero then there is nothing you can do. The program is erroneous and it is best to be fixed than try to somehow disguise it by throwing/catching an exception
Java exceptions are checked only by the compiler, however java designers decided to split them into multiple categories, basically involving the superclass being extended
java.lang.Exception - known as checked exceptions
java.lang.RuntimeException known as UNchecked exceptions - as bonus java.land.RuntimeException extends java.lang.Exception (to ease the handling in catch blocks, and not only)
java.lang.Error - errors, also unchecked and rarely needed to be handled by user-space code, but knowing them and their variance is a major plus. They include (most famous): linkage error, stackoverflow, out of memory, assertion errors
java.lang.Throwable - Checked! and the mother of all exceptions, few need to directly subclass it, but some does for unknown reasons
So it's about need to declare the exceptions and taking care of proper propagation (on compile only level), unchecked ones are auto-propagated and the developer is not expected to provide handling of unless needed.
Checked ones are generally expected to happen and require extra verbosity in the java, already fluffy code.
Worst practices include: catch (Throwable t){}, for many a reason, usually errors shall not be handled unless necessary and most errors usually spell the thread death either ways.
Short answer as some pros and cons have been named: It is a matter of personal or organisational style. None is functionally better than the other. You (or your project) will have to make your own decisions about whether to use checked or unchecked exceptions, or both.
Oracle's Java Tutorial advices you to use checked exceptions for all errors the application can recover from, and unchecked exceptions for the errors the application cannot recover from. But from my experience most applications may recover from most (maybe not during startup) exceptions. The action that failed will be aborted but the application stays alive.
I would rather only use either checked exceptions or unchecked exceptions. Mixing may result in confusion and inconsistent use. Be pragmatic. Do what makes sense in your situation.
Never explicitly throw RuntimeExceptions. If you ever think you need to then just let the runtime do it rather than using throw.

Categories

Resources