A good example of this is when the Integer object’s static parse­Int() method is called on to convert a String object to an int primitive. It would be cumbersome and backwards if Some­Object were required to first determine whether or not the String actually contained digits rather than alphabetic characters every time it wanted to perform this conversion. Therefore, the Integer object’s parse­Int() method, as it evaluates each character in the String, may determine that the input is invalid and throw a Number­Format­Exception. The following is a fragment from that method which shows how it makes such a decision as it checks each character.

digit = Character.digit(s.charAt(i++),radix); if (digit < 0) { throw new NumberFormatException(s); }

The creation of an exception begins with the new keyword, just like any other object. The difference, however is the throw keyword, which triggers a special set of events in the virtual machine which makes the whole error handling mechanism work. While an exception can be created without actually throwing it, only an object extending Throwable can be thrown.

When an exception is thrown in a method and it is not caught in that same method, the execution of that method terminates back to the calling method. No value is returned, nor does the variable on the receiving end get anything. Control is handed back to the calling method, but only for the purpose of catching the exception. If no such catch is attempted, or it is the wrong type of catch, then control continues up the method invocation stack. If the exception cannot be properly caught when it reaches the top of the stack, then the running thread expires prematurely and a stacktrace is written to the Java console. This next diagram illustrates how this works.

Whenever you suspect that a String may fail a number conversion, it is a good idea to build a try-catch block around the method call. This is optional, but of course the alternative is that your program may crash. Here is an example that would work in the above situation:

String s = "not a number"; int i = 0; try{ i = Integer.parseInt(s); } catch{ System.out.println("That was not a number."); }

There are a number of things that could be done here in place of the output message. For instance, perhaps doing nothing makes sense if the variable i should be zero when s is not a valid integer, as it has already been initialized to be. The catch block is the developer’s opportunity to perform a recovery appropriate to the situation.

One of the things that makes error handling so annoying in Visual Basic is that its global Err object has no context. (Imagine two threads fighting over who can report their error – good thing VB is crippled with single-threaded execution.) When an error is raised, the Err object is assigned a 32-bit integer identifier that then needs to be tested and reacted to. No matter what variety of error is raised, the same code must decide how to handle it1. In modern object-oriented languages, every error is its own object and can take on behaviors of its own.

This is where exceptions lead to generally cleaner code. Errors do not need to be checked for and handled at every point where they might occur. The Integer.­parse­Int() method, for example, throws Number­Format­Exception in nine places, but doesn’t have to handle it at all. It does this because there are nine possible causes of the exception, and with each one it can throw the exception and know that the calling method is expected to handle it. The functional code and the handler stay separate which reduces the overall amount of code and improves maintainability, not to mention performance.

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-3) was last changed on 07-Jul-2007 00:02 by JanneJalkanen