ID:182400
 
I'm learning Java at the moment and I've come across exceptions in various tutorials yet I don't quite understand them. Do you have to manually tell it what error message gets sent when something exceptional happens (such as divison by zero)? What else can they be used for? (I know that a program doesn't crash when a method throws an exception if you use a try..catch block.)
I don't know Java, but from what I understand the purpose of exception handling is to catch errors and handle them specially. As in when dividing by zero, if you don't catch the expression the program will really try to divide a number by zero, resulting in a crash, but if you catch the error you can stop that from happening.
Exceptions are also used in the try..finally block, where the machine will attempt the contents of the try block, and whether or not execution is successful (i.e. it doesn't matter if an exception is raised) the finally block will be executed. This is useful for e.g. file access because it means that if an error occurs the file doesn't remain locked.
Kakashi24142 wrote:
Do you have to manually tell it what error message gets sent when something exceptional happens (such as divison by zero)?

I don't know about Java, but C++ allows you to catch(...), which is kind of like the "I don't know what I'm catching" exception handler. Still, it's better to catch the exceptions you do know before handling it to the catch-all, because then your program can respond more correctly to each exception, rather than just throwing out some generalized "Something happened and I need to crash now please" behavior.

What else can they be used for? (I know that a program doesn't crash when a method throws an exception if you use a try..catch block.)

When writing your own classes and such, if a method's input is incorrect or something, you can throw your own custom exception. Then whoever uses your class (including yourself) can catch the exception if there is an error in the input. For example, pseudocode:

void HandleStrings(string1, string2)
// string1 and string2 should be same length
if string1.length != string2.length
throw DiffLengthError
else
// handle the strings


Whenever a program goes to use HandleStrings(), they'll pass two strings. It returns void, meaning that one can't check the return value of it to test for failure. Instead, you don't need to test anything outside the method, because it'll jump straight to your exception handler if you have one. Also, the need for a redundant string length comparison before calling the method is unnecessary, since the method checks it already before handling the strings.
Exceptions are just a way for a program to say "OH NOEZ! SOMETHING BAD HAS HAPPENED!" without just crashing. In BYOND, if a procedure accesses the 14th element in a list of size 13, the procedure just crashes. In Java, you can write some code that says "Whoops, that was wrong, oh well. This is how I'll fix the problem". Instead of the program just crashing, you can fail gracefully.
In response to Jp (#4)
Jp wrote:
Instead of the program just crashing, you can fail gracefully.

Depending on the error you may be able to not even need to terminate at all.

George Gough
In response to KodeNerd (#5)
I know we're going a little off-topic, but he did just say fail, as opposed to terminate. But yeah, I appreciate what you are saying. I suppose (funnily enough) that 'you can just handle it, potentially carrying on successfully, failing gracefully or terminating gracefully, depending on the situation.' would have been better.

Exceptions are basically a mechanism for allowing error handling at a level in the call-tree that makes most sense. Sometimes the callee doesn't have enough information to make a decent judgement call on how to handle an error, but the caller may, or the caller above that etc. Hence Exceptions get thrown up the call-tree, ultimately ending up at main, or flying at the VM itself.
In response to Stephen001 (#6)
Thanks everyone. Does this mean I need to memorize all the common exceptions and know when to check for them so I can "fail gracefully" when an error occurs?
In response to Kakashi24142 (#7)
The Java API (http://java.sun.com/javase/6/docs/api/) will have most of the Exception stuff documented, including when the Exception is liable to be thrown. Rather unfortunately, there are two types of Exception it seems, in Java. Those declared explicitly by:

throws IOException, FileNotFoundException ...

The compiler will tell you if you're ultimately not catching these, that is, if they will get thrown all the way up to the VM and cause a crash.

Then you have the implicitly declared Exceptions, such as NullPointerException, which are supposed to only come about due to run-time problems, like memory issues etc. The compiler will not warn you about these, as such it might be wise to have:

catch (Exception e) {
e.printStackTrace();
}

At some points higher up in the call-tree, for debugging purposes. Because of Java inheritance, all Exceptions inherit from java.lang.Exception, so catching that gets 99% of problems. Exception isn't too useful though, seen as it's not too easy to discern what went wrong from it, hence you end up with multiple catch blocks instead:

try {
// Code.
}
catch (IOException i) {
// Permissions problem?
}
catch (FileNotFoundException f) {
// Someone deleted out file, perhaps.
}
catch (Exception e) {
// Catch-all.
}

Ideally, you handle the exception as low down as you sensibly can. A lot of this will come with experience.