I'm writing a method with the following signature:
public void setCell(int index, String value);
The problem with this method is that the index parameter has a finite range decided at runtime, and the caller may accidentally use an out-of-bounds value for it. What should I do in this case?
I can think of three options:
Nothing -- let the whole thread crash and burn with an uncaught runtime exception
Immediately return if the index is out of bounds -- the caller will be unaware that the method failed but the program won't crash
Throw an exception / force the user to wrap calls in a try/catch block. This seems a bit overkill and tedious for the user of the method
In general, how do you decide which of these options to use?
Ideally, you'd want to throw an exception as early as possible (fail-fast) or let the exception happen naturally in which case it would hoist or bubble up to the calling method to indicate the cause of the exception rather than trapping the exception in a try/catch and letting the execution continue.
I'd also avoid option 2 which immediately returns if the index is out of bounds due to the fact that it's now impossible for the calling method to know if execution has successfully completed or not. in-fact this is a means of helping the program hide a bug rather than trying to signal it, which in a way relates to JB Nizet's comment.
It's better to keep the caller informed if the method being invoked successfully finished doing its logic or for some reason, it failed to do so.
throw an exception
You can even implement your own exceptions. Which case to use depends on your application and application design. Having uncaught or unhandled exceptions is probably the worst case most of the time.
if you have an user interface you can usually handle exceptions and inform the user, if you are implementing library functions you'll rather throw them and pass them to a higher level.
Related
I was just reading about try-catch blocks and exception handling, and I read something in the "Propagating IOExceptions" section that confused me a bit. Jenkov says that if Method C throws an IOException - public void MethC() throws IOException{}- but does not have a try-catch to handle it, it will roll up the call stack to a calling method that may have a try-catch to handle the exception
The whole point of a try-catch-finally block seems to be to handle an exception that would, unhandled, crash your program right? Well, then why let the exception roll back up the call stack to a try-catch somewhere up the chain? What is the value? If anything, it seems to me that letting the exception roll up the chain, instead of handling it right away would just compromise the program and be bad form and cause inefficiencies or be inefficient.
The whole point of a try-catch-finally block seems to be to handle an exception that would, unhandled, crash your program right?
Not exactly. An exception doesn't always cause a crash the program, it can "just" cause some part of it to not work properly. It is true that try-catch-finally are used to handle exceptions.
Why let the exception roll back up the call stack to a try-catch somewhere up the chain? What is the value?
Because sometimes the method in which the exception occurs is not suited to take the decision on how to handle it.
I'll give an example: look at the method Integer.parseInt(String s), it takes a String and tries to convert it to an int according to its content. Since this is done at runtime and you can't know ahead of time what the string would be, you have to consider that the string will not be a number, say, if it comes from user input. If it's not a parsable string, how do you want the method to handle it? Why should it get to decide the outcome of an operation it was not designed to perform?
This is why the method throws a NumberFormatException - if the string does not contain a parsable integer. Whoever called the method has the scope to decide what should be done as the method is dedicated only to convert the string to a number. It can either ask for a new string instead because the last one was not valid, or just use a default number instead as a sort of placeholder.
A real-life analogy: the boss tells his secretary to schedule a meeting with en employee at a given date, The secretary finds that the employee is on vacation on that date. Should the secretary handle the situation themselves? Probably not. Instead, they would "throw an exception" to their boss along the lines of "InvalidMeetingTime" and let the boss decide what to do.
It seems to me that letting the exception roll up the chain, instead of handling it right away would just compromise the program and be bad form and cause inefficiencies or be inefficient.
That is why it is the responsibility of the calling scope to delegate the event properly. Either handle it itself or pass it upwards until something does handle it.
See more at Lesson: Exceptions.
It's perfectly fine to let an exception percolate up the call stack as long as your design intends it. A simple example is if your main method has a try/catch block around a call that can have a very deep call stack. If an error happens at any point, it can throw an exception and the program can end gracefully with the catch in main saying "Sorry, the following excpetion happened, so the program is ending".
It would be bad design to never catch an exception and let the program terminate abnormally, but there's nothing wrong with catching it many levels up from where the actual exception happened if that makes sense in the instance.
Often a problem happens deep in the code and the right way to handle it (show a dialog? print an error? handle it quietly?) may be different through different call paths, and the choice of what to do can be made somewhere else along the call stack.
In general, an exception should be handled at the place in the call stack that is capable of handling it.
For example, suppose you have a library method that takes a file-path and returns the entire contents of the file, as a byte[]:
public static byte[] readFile(final String filePath) throws IOException {
final InputStream inputStream = new FileInputStream(filePath);
...
}
There's no way that this function can "handle" a nonexistent file; if new FileInputStream(filePath) raises a FileNotFoundException (which is a subtype of IOException), then the best thing this function can do is notify its caller. The caller has more information about where filePath came from, and about what it means if the file is missing; for example, if filePath was typed in by a user, then maybe this means that the program needs to show a message to the user to let him/her know about a probably typo. The point is, readFile doesn't have any of that information, and can't make the right decision. So it should let the exception propagate up to a caller who can.
Sometimes letting the exception rolling back up the stack would be helpfull for many reasons (Service, Restfull api, etc.). Let's say you have a method that display or parse a file and takes a filename as parameter, you don't know who's going to use your method or for what therefore by throwing an Exception you give the developer another chance to display his message or handle it as he wishes.
I'm working on a Java project and I've come upon an interesting design issue. It's not exactly a problem, but it is a bit ugly with the obvious solution.
I have a class implementing Callable, although with the current implementation it could just as easily be a Runnable as I'm not interested in the outcome, at least not as far as the calling thread is concerned. The calling thread will drop a number of these into a thread pool. Each of these Callables will have a batch of data that was obtained from an external service. The Callables will perform a number of actions, many of which involve making further calls to external services. As a result, there are a good number of places where various Exceptions could be thrown.
The issue I find is that depending on where the Exception occurs, I may need to take different actions. If it happens at point A, then delete the data on the external service. If it happens at point B, move the data to a different location on the server. If it happens at point C, just log it and do nothing further, etc. Any number of Exception types could be thrown at multiple points, although I don't think I'll need to do much filtering on the type itself, but more that one occurred.
The Callable itself isn't terribly huge, so there's not a great deal of code to mess with. However, I am hesitant to kludge it up with a ton of try/catch blocks to handle every possible point/Exception that may need different handling. I realize that this may really be the only viable solution. I don't really have control over most of the Exceptions that will be thrown (maybe a handful) without catching an existing one and rethrowing my own, which seems a bit redundant. I'm wondering if there's a good pattern or method to handle this sort of thing.
I've considered an exception handling class, but I'd still need to catch each Exception somehow and pass it to the handler as the point at which the Exception was thrown is important. I could break the Callable down into more atomic classes, each with their own small block and handling, but that would be trading one kludge for another. Catching everything in the call() method outright or by grabbing the Exception from the Future in the calling thread really isn't an option as this will lose the data on where it occurred unless I want to parse the stack trace, which isn't exactly viable.
Can anyone shed some light? Maybe I'm just quibbling over the try/catch blocks and should just go ahead with it, but I feel like there must be a better way...
Hmmm, it does occur to me that annotations on methods might help here. I could break down all methods until there's only one possible exception-throwing piece of code in each. Annotate each of these with a custom annotation that dictates what is done when that method throws an exception. I'm not sure if it is possible (an exception would somehow need to be caught right there as it may happen within a loop going over each piece of data and only one piece may be problematic, or at least somehow mark that piece for processing further up the chain), but perhaps this could mitigate the need for lots of try/catch blocks and instead handle the behavior with a single annotation and a handler class to deal with the exceptions. I don't believe it's possible to dictate behavior this way with an annotation, but I'd be happy to be wrong on that.
I know that Error is Throwable (so it can be handled) and Error handling isn't best practice but suppose we have a requirement to catch all Error.
It is possible in general? I mean what about Errors which can appear in daemon threads? They will crash jvm and I won't know about it.
And can I miss Error even if I surround main(String... args) with try-catch?
You can catch the uncaught exceptions via Thread.setUncaughtExceptionHandler()
Set the default handler invoked when a thread abruptly terminates due
to an uncaught exception, and no other handler has been defined for
that thread.
Uncaught exception handling is controlled first by the thread, then by
the thread's ThreadGroup object and finally by the default uncaught
exception handler. If the thread does not have an explicit uncaught
exception handler set, and the thread's thread group (including parent
thread groups) does not specialize its uncaughtException method, then
the default handler's uncaughtException method will be invoked.
Whether that's a good idea is another question (!). It may be that you simply want to clear up resources, shut down connections etc., log the issue and/or alert the user. If you do have critical issues like OutOfMemoryErrors then there's little else you can do.
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.
Now, since Error does indeed extends Throwable, it is possible to catch 'any' error via a simple try-catch statement as follows:
try{
//Error causing code here...
}catch(Error e){
//Handle error here...
}
However, since errors come in different forms, a thrown error may or may not be accompanied by a change in the jvm's behaviour to cause unexpected results.
Consider the Error OutOfMemoryError. When this Error is thrown, the JVM's heap may be so full that any type of handling code results in another OutOfMemoryError being thrown, voiding any attempt of recovery.
Furthermore, even when running on the "primary" thread (the one the application starts in), a error could cause a JVM to crash before every throwing a Error.
Looking at the description of VirtualMachineError (of which Errors such as OutOfMemoryError, StackOverflowError, InternalError, etc are subclasses of) we see:
Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operating.
The javadoc itself states that the jvm no longer can continue operation normally much less allow a programmer to just 'handle' them away.
On the other hand, errors such as UnsatisfiedLinkError generally do not cause a problem with the jvm straight away and can generally be handled (whether this is good practice is debatable). I personally have once used a structure that involves handling a UnsatisfiedLinkError to determine the correct library to load for JNI.
Now, can all errors be handled? Theoretically yes, if we assume that the JVM can continue operation perfectly despite claiming to have failed fatally... With that in regard, practically only a small subset of errors are handleable. Whether or not these small subset of errors should be handled is also a highly controversial topic.
You can handle exceptions, but you can't handle errors.
Does java has library exception class which means actually not an error, but good termination? I know I can make my own class or use null, but wish to know.
EDIT 1
I want to use exception object as an old fashion return code for a method, so I need something equivalent to ERROR_SUCCESS code in Win32 API.
Exceptions in Java are meant to be used for abnormal termination only. Using them to flag correct termination should be considered really bad practice.
You might use return values instead.
To directly answer your question: No. There is no standard Java exception that means "this is a normal termination".
If you wanted to, you could define a custom exception that meant this for your application.
However,
... using an exception for "normal control flow" goes against the strong recommendations of the Java designers, and a Java "Best Practice" rule that has pretty much universal acceptance. This is not to say you should NEVER do this. It is just that the cases where it is justifiable to do this are VERY RARE. (And you'd need to take special steps to avoid grossly inefficient code ... )
Anyway, the fact that it is (almost) always a terrible idea to use exceptions for normal flow control explains why a standard exception was never created. The Java designers clearly didn't want to appear to be encouraging this practice.
The closest thing to a "good termination" signal I can think of is not an exception, but a call to System.exit(int) with 0 as argument, to indicate to the operating system that the program ended successfully. From the javadocs:
Terminates the currently running Java Virtual Machine. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination. This method calls the exit method in class Runtime. This method never returns normally.
As has been pointed out, an exception is not to be used to inform of a "good termination", quite the contrary.
No. Exception means exceptional situation. You should structure your program flow so that exceptions are thrown only for exceptional situations, rather than on the normal flow.
So, if you want to return "success": return true or some enum Result.SUCCESS.
Exceptions are mean to denote that something went wrong. Different exceptions depict different items which went wrong and will thus cause the program to terminate if not handled. Something successfully finishing is not an exception.
I think what you need to do is to either return a particular value, or else, make your application fire some sort of event. In this case throwing exception is not (at least for me) recommended.
Depends what you define as "good termination" I guess - is a security exception good because it stopped someone from hacking your system? It's not really an error, but it is an abnormal situation that you need to handle.
In general exceptions are designed to be used for exceptional conditions only (which may or may not be an error in your code - it could mean that some resource is unavailable, or a security check failed etc.)
If you are using exceptions for regular control flow (i.e. they are getting thrown in normal, expected circumstances) then you are probably doing something wrong.
Maybe you mean an InterrupedException? This one is thrown, when you wish to terminate a thread gracefully.
As some other responses said, when there is no exception, nothing is raised.
Therefore, you can just your code for the "no-exception" into the try block after the rest of instructions. Something like:
try{
//code here
//code of no exception
}catch(Exception e){
//nothing or exception code
}
or you can just create your own exception by doing a class that extends Exception
I've got a decently complex little game going on in Java (solitaire, essentially like the Windows version), but I have yet to do very much error handling.
Almost all of the methods across my classes will end up either getting called by an initial constructor (eventually main()), a paintComponent() method, or a mouse event. So, my question is, is it bad practice to just use "throws Exception" on all of my lower-level methods, and only do a try/catch at my top-level methods to catch ALL the errors at once? (e.g. 3 try/catches - one for the painting, one for mouse events, one for the main method).
I realize this prevents me from easily dealing with errors on-the-spot, but I don't really plan on doing that anyways. My error handling is going to consist of writing to a log, telling the user, and killing the program. Keeping this in mind, is there anything bad with doing my error handling this way?
It depends on how you want to approach the situation.
If you just want to catch any possible exception and you don't mind about the handler code, you could simply use "throws exception", and there's nothing BAD with it either. It's like a try-catch block that covers all the function.
If you want to write specific code for specific exceptions, you should use try-catch blocks to write appropriate code for each handler.
Based on what you're saying, any caught exception would just notify the user and exit the application. Well, in this case you could just use the first approach. It's not necessarily the BEST approach, and neither is killing the application, however, if that's your strategy you could just use "throws" for each function.
Hope that helps!
If that's all you wan't to do in a case of an error, then it makes perfect sense to do it that way. This eliminates code duplication and scattering of related code. However, if you're thinking of changing how things work in the future (if there's a possibility of this happening), I would suggest to try and push the catch down as far as possible (maybe even eliminating the need for exceptions at all and just logging and exiting right away).
If you use the exception's inner fields (specifically message, which you can set in construction time), you can even eliminate the need for 3 different catch blocks and just use one (depending on your actual actions in case of an error, of course).
I wouldn't - the big reason being that it breaks encapsulation. The reason why this is important in this case is that your error handling code has one of two futures:
Becoming enormous to handle in an informative way every error the program can throw.
Be tiny but not helpful at all: "Some error occurred somewhere".
To my mind, the best structure is to catch the error, log it, alert the user, and exit as far down as possible. There's nothing that says your mouse handling code can't exit, right?
In fact, I would create an error handler class that you can call from just about anywhere, and it handles the notification and logging. Then your exception handlers can just populate it with the message to display/log, and all other code is shared. It will cost you less typing to delegate to this class than adding throws Exception at the end of every function everywhere.
If you must have a top level handler, it should just catch any unexpected runtime errors, so that you can log it and show the user that the program is really quitting for an error, and not just dump to the desktop. All other errors - even if you just want to bail out - should be caught as close to "where the exception has meaning" as possible.
I do the same thing as you are describing most of the time. What you're basically doing is working around the stupid checked exceptions that Java has. It shouldn't even be necessary to add 'throws Exception' everywhere.
If I'm working on an API that other users will use I may create specific exceptions to show what is going on in case they want to handle different exceptions in different ways.
If an error is severe enough to always exit the program, you may be better of throwing a RuntimeException instead. They are used to indicate unrecoverable errors and will avoid problems with putting "throws Exception" everywhere. You should have a handler for RuntimeExceptions anyway to provide a user-friendly error report in case they happen.
If you throw checked exceptions, they should be as specific as possible. Throwing and catching Exception can hide other exceptions that are thrown (including RuntimeExceptions) that you didn't intend and could have been handled differently. If you want to throw a general exception, you can always create your own exception class and throw that instead.
The exception handling can depend on the context so there's not one way to handle everything. If the user clicks a button to open a file and there's an error reading it, then it would be ok to throw an IOException up to the UI layer and display an error message there. On the other hand, an IOException while creating a temporary file could be handled lower down by retrying in another directory.