Reputation: 31
I was wondering what is the proper convention for handling a try/catch block. It is pretty obvious what should be within the try
block but what about the catch
block?
Can I write a message to the user like the following:
do {
try {
System.out.println("Pi to the number of decimal places:");
Scanner in = new Scanner(System.in);
userNth = in.nextInt();
} catch (Exception e) {
System.out.println("Error: Enter a number between 1 and 100");
}
} while(userNth < 1 || userNth > piDecimals);
Or is this bad practice?
Upvotes: 2
Views: 3539
Reputation: 96444
Exception-handling is not the place to make rash assumptions; usually by the time this part of your code has been executed it's because something unanticipated has happened, this is when you want to be most careful to be accurate about detecting and recording what happened so that you can tell what needs fixing.
The choice of Exception as the type of exception that gets caught is too broad. The method you're calling throws 3 different exceptions for distinctly different reasons; only one of which is something that should be caught here. Also unchecked exceptions like NullPointerException will get caught by this. If you were to add some code to this catch block that inadvertently introduced a NPE it would be hard to figure out what went wrong. Your overbroad catch can result in bugs not being found or errors not getting handled properly.
(Btw Makoto makes a good point that nextInt isn't what you should be calling here anyway.)
Not logging the exception can be acceptable in narrow cases where you're certain of what the exception means (for instance, if you caught InputMismatchException, or NumberFormatException in Makoto's example code). But in combination with catching Exception it has the capacity to hide errors and cause confusion.
You likely chose to catch Exception because handling a bunch of different checked exceptions, most of which seemed unlikely to ever happen anyway, seemed like an intolerable nuisance. Providing a consistent way of handling and logging exceptions will help, by providing a reasonable default case for exceptions you don't know what to do with. That way if you see an exception you just can't handle, you always have the option of letting it be thrown (possibly catching it and wrapping it in an unchecked exception), knowing that if thrown it will get logged and end your program.
For a very small command-line program sometimes it's entirely ok to let exceptions that you can't handle be thrown from main (by adding throws Exception to the main method). This is ok for toy examples, small school projects, etc.; I'd only use it in production code if there was a plan for logging the output (like a batch file that redirects stderr to a file):
public static void main(String... args) throws Exception {
... application code
}
In most cases all the main method code should be placed in a try block where any Throwable is caught and logged:
public static void main(String... args) {
try {
... application code here
}
catch (Throwable t) {
logger.log(t);
}
}
Either alternative makes it less tempting for you to inappropriately swallow inconvenient checked exceptions.
Upvotes: 2
Reputation: 106498
In all actuality, this code is not going to function the way you intend it to. There are two key reasons for this:
nextInt()
blocks until it receives an integer; that is, it's not going to care about what input you give it until it reads an integer, anduserNth
and piDecimals
, one or both of those variables may not be defined, thus preventing compilation.Also, don't catch Exception
. Be as specific as you can when catching exceptions, since Exception
also includes some nifty and dangerous RuntimeException
s like NullPointerException
.
What you're looking to do:
userNth < 1 || userNth > piDecimals
.To that, we should look to get the right exception thrown by parsing the input as a string first, then as an Integer
:
try {
System.out.println("Pi to the number of decimal places:");
userNth = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: Enter a number between 1 and 100");
// You have to set this value to something so that userNth is defined!
userNth = Integer.MAX_VALUE;
}
The other part to this is that you have to decide what message you show if userNth > 1 && userNth < piDecimals
, since your try...catch
isn't going to cover that. This, I leave as an exercise for the reader.
Upvotes: 1
Reputation: 556
Simple Answer: what you wrote is fine
Longer Answer: try-catch blocks are for executing code that may throw an exception, and then handling said exception if it occurs. In general, the catch block should have code that handles the exception however you need to handle it. If the statement you currently have is how you want to respond to an exception, then it's fine by convention. Some common things to do in a catch block are:
printStacktrace
on itBut anything that fits your exception-handling needs is fine
Upvotes: 1