java boilerplate

Thursday, December 01, 2005

Ignoring exceptions.

The compiler error 'exception either needs to be caught or thrown' is just there as a safety measure; a hacked version of javac that silently ignores these problems will produce perfectly valid class files. It is in fact already possible to throw any exception 'on the sly' (see java puzzlers, the book. The first comment of this entry also explains some ways on how this can be accomplished).

Sometimes one is forced to catch an exception which doesn't really need catching. In some cases, the exception in question can't actually ever happen (such as UnsupportedEncodingException when using a direct reference to "UTF-8", or IllegalAccessException when using reflection to access fields or methods that you just explicitly enabled access on using the setAccessible method). At other times the exception is extremely unlikely; the rather catastrophical failure of silently passing it up the stack is in fact acceptable. At still other times the code is used only by programmers themselves, such as utility software or test code. In many such circumstances, being forced to set up try/catch blocks (due to ie restrictions on what exceptions may be thrown because you're implementing an interface or overriding methods) is annoying, hinders readability, and, according to various books, including 'java puzzlers', introduces significant performance penalties.

We suggest a method to manually 'override' the failsafe system that ensures all non-RuntimeException/Error based exceptions are handled one way or another.

We offer two solutions for this; an annotation based solution, and a keyword based solution:

old code:
     public Reader foobar() {
try {
return new InputStreamReader(System.in, "UTF-8");
} catch ( UnsupportedEncodingException e ) {
throw new Error();
}
}


new code - annotation based method:

     @IgnoreExceptions(UnsupportedEncodingException.class)
public Reader foobar() {
return new InputStreamReader(System.in, "UTF-8");
}


where the IgnoreExceptions annotation looks like this:

     @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD)
public @interface IgnoreExceptions {
Class[] value() default {Throwable.class};
}


the other keyword based method:
(This way requires a new keyword, 'ignores'. This could pose backwards compatibility problems)
     public Reader foobar() ignores UnsupportedEncodingException {
return new InputStreamReader(System.in, "UTF-8");
}


ignores and throws are both allowed and can be applied to a method in either order, similar to how both implements and extends are legal on a class declaration.

1 Comments:

  • The general way of throwing a checked exception on the sly is by using the Thread.kill(Throwable t) method. It works, but the method is deprecated.

    the Class.newInstance() method can also throw checked exceptions silently.

    Starting with java 1.5, you can use some fancy generics footwork to throw any exception.

    For more information, see a chapter in 'java puzzlers' by Josh Bloch.

    By Blogger Reinier Zwitserloot, at 4:44 PM  

Post a Comment

<< Home