What are the caveats of using Exceptions? I heard they were slow and should be avoided. What are the alternatives? Judiciously check all data with if/else statements?
I never experienced that Exceptions were a performance bottleneck. I think when an exception is thrown, you just need to be aware that some objects are created so you might get a bit of garbage when your code throws a lot of exceptions in inner loops or something.
As always, I’d say just design it the proper way. Which is using exceptions where applicable and if it turns out to be a performance bottleneck after profiling, do something about it then.
Erik
Exceptions are slow - if they are thrown. In addition to object creation (which is non issue), you need to create copy of entire call stack, unwinding frames - this is sometimes non-trivial, especially in presence of inlined methods.
I don’t think that anybody actually suggests avoiding exceptions totally. But, given error-free execution of program, you should not rely on exceptions as a method of controlling program flow. Best example is opening a file - you expect it to be there and in normal case, everything goes without exception. If it is suddenly missing or non-readable, you can throw exception - user will be probably alerted and asked for action anyway, so any millisecond-wide costs are not noticeable.
Do not use ArrayIndexOutOfBounds to terminate loops. Do not use NullPointerException to manage non-initialized element of some map if it is bound to happen often. Etc, etc.
BTW, as far as costs are concerned, one of the MAJOR areas where Exception cost is visible is class loading. If you have a number of classloaders, with classes distributed between them, there is no easy way to check if class if defined there - you need to ask for it and catch exception if it is missing. This was a major problem with Netbeans - they had many jars with classes, and tens of thousands exceptions thrown during application startup, because class was looked for in wrong jar at start. AFAIK, after performing some optimalization (providing info which class should be looked for in what jar) they had reduced startup time from 25 to 20 seconds or something like this.
As for Erik suggestion of profiling first, please note the “using exceptions where applicable” part. If you will design your control flow to be exception driven, changing it will be very hard later. IMHO, it is a thing which should be done right from very start.
My rule of thumb is quite easy - use exceptions for exceptional situation. If all variables outside scope of application (filesystem, network, memory, user input etc) are correct, no exception should be thrown. Of course, it is sometimes not possible, but for me it is a goal which helps me to decide when use exception and when do it ‘manually’.
An even easier way to summarise that: never rely on exceptions for your code to work properly.
Cas
An alternative would be to return a ResultObject. The exceptions could have static ResultObject(s) thus no new classes would have to be created in comparison to thrown.
[quote]My rule of thumb is quite easy - use exceptions for exceptional situation. If all variables outside scope of application (filesystem, network, memory, user input etc) are correct, no exception should be thrown. Of course, it is sometimes not possible, but for me it is a goal which helps me to decide when use exception and when do it ‘manually’.
[/quote]
Basically that’s exactly what I meant by ‘where applicable’, I was just a bit vague
The cases where I use exceptions are the cases where it won’t matter much if an exception is costly or not, 'cos those are the cases where we’re screwed anyway
In the really performance critical parts, I don’t even want to be checking data if possible in order to see what kind of ResultObject I’d want to return at all.
So, for example in Cosmic Trip exceptions might be thrown at start up, shut down, sending a high score to the server, fetching the high scores from the server or handling a complete crash for cases I didn’t see coming (so that the game shuts down when something occurs I didn’t see coming).
But, if you really demand more exceptions to be handled in your performance critical part (the running game I imagine), something like ResultObject you described might be cheaper than exceptions if an exception would be thrown.
OTOH I can imagine checking your data constantly to return a proper ResultObject every time could even cost you more in the case an Exception would not be thrown, which is what ‘normally’ would be the case.
[quote]Do not use ArrayIndexOutOfBounds to terminate loops.
[/quote]
Actually when I think of it, I did exactly that in early version of the CottAGE emulator in a part that took >50% execution time (an inner loop somewhere in the rendering). It was kind of a dirty workaround of a bug in the clipping code. The strange thing is, it didn’t make much of a difference (not noticable) when I fixed the bug and removed the try and catch and the ArrayIndexOutOfBounds used to happen quite a lot… Hmmm… :-/
Throwing an exception isn’t bad, however creating an exception TO throw can be slow, mostly because it has to extract and create a representation of a stack trace.
HOWEVER it is a given that you should NEVER NEVER use exceptions for control flow. Its just bad coding and leads to less maintainable code. Exceptions are for exceptional conditions, those conditions you expect to encounter extremely rarely, if ever.
If there IS a reasonable return value from a call it should return it, not throw an exception.
I was thinking of something like this. Any input in contrast to exceptions?
With the below I can do the following:
ResultObject resultobject = doSomething();
if(resultobject.getResult()==null){
System.out.println(resultobject.getError());
}
public class ResultObject{
private MyObject result=null;
public MyObject getResult(){
return result;
}
private static int final ERROR_NONE = -1;
private static int final ERROR_TYPE_MISMATCH = 0;
private static int final ERROR_TOO_LARGE = 1;
private int error=-1;
public int getError(){
return error;
}
}
You’d only really want to use that particular pattern if an “error result” was not an expected result.
Cas