Monthly Archives: November 2006

Generic exceptions

This post is about a language mechanism they snuck into Java in 5.0 which I recently discovered. Well, to be honest I didn’t even discover it myself: most of what I’ll describe here was pointed out to me by Peter Ahé. But as far as I can tell it’s not widely known or used so I thought I’d take the opportunity to spread the word.

Here is a standard generic method, just to refresh yor memory and get into gear:

public static  T getFirst(List ts) {
return ts.get(0);
}

It takes a list and returns the first argument. It has one type parameter which is used both in the return type and in the argument types.

It turns out, however, that you can actually use type parameters in one more position in a method declaration: throws clauses:

public interface IRunnableextends Throwable> {
public void run() throws T;
}

This interface has a single type parameter which specifies which kind of exceptions may be thrown from the run method. I’ve always just assumed that you couldn’t do that so I’ve never even tried — but it turns out that you can. As far as I can tell there is no explicit rules for this in the language specification; it’s just not disallowed. The only mention I’ve been able to find of it in the JLS is a footnote in section 8.4.6.

A concrete subclass of IRunnable could be

public class FileCreator implements IRunnable  public void run() throws IOException {
// create a file
}
}

If you call the run method on a file creator you will be required to catch or declare the IOException, just as usual. What if my runnable doesn’t actually throw any exceptions? Well, you can just use IRunnable.

Since the exception type is just an ordinary type parameter, you can do all the complex stuff you can usually do with type parameters. You can leave them out:

IRunnable rawRunnable = ...;
rawRunnable.run(); // throws Throwable

and you can use wildcards

IRunnableextends DebugException> debugRunnable = ...;
debugRunnable.run(); // throws DebugExceptions

There is one thing you can’t do, though: throw multiple exceptions:

public class MyRunnable implements IRunnable<...&gt {
public void run() throws IOException, IllegalArgumentException {
// ...
}
}

As far as I can tell, there is no type argument you can give to IRunnable that would allow run to throw more than one exception type.

In my checked exceptions RFE, one argument I used was that if you write a general visitor there is no orderly way to propagate checked exceptions out of the visitor traversal — you have to handle those exceptions locally. But that is not actually true: you can just parametrize the visitor with the kind of exception it might throw and then parametrize it with a checked exception if any of the methods might throw one. I’m not sure I would do it that way, but it’s certainly a possibility at least in the cases where the visitor can only throw one kind of exceptions. But while this mechanism solves that problem, it creates another.

Since this mechanism relies on generics it can also be fooled, as you can with traditional generic classes. Here’s an example of fooling the static type system:

ListList ints = (List) strs; // warning, but legal
Integer i = ints.get(0); // cast error

With generics some operations, such a the conversion from a list of strings to a list of integers, cannot be checked at runtime. Instead, the runtime system has to wait until it has enough information to perform the check. In this case, instead of checking that the list is really a list of integers in line two, it checks that the element extracted in line three is an integer.

The reason why this works is that java’s generics were designed such that even though you might fool it in some cases, you will always be caught before you can do any damage. The type system may not be able to tell a list of strings from a list of integers, but if you try to assign something to an integer-valued variable that the static type system is unsure is an integer, it will insert a runtime check.

For this to work, however, you must eventually be in a situation where you have all the type information available to insert the check. And with exceptions that is no longer the case. Observe:

extends Throwable> void cloakException(Throwable e) throws T {
throw (T) e;
}

void myMethod() {
try {
throw new IOException("Harsh!");
} catch (IOException ioe) {
this.cloakException(ioe);
}
}

Here cloakException performs an unchecked cast to T and under normal circumstances the caller of cloakException, who has all the type information, would have been able to insert a delayed check that the conversion was really legal. In this case, however, the object is not returned but thrown. That means that the caller never gets a chance to verify the conversion. This essentially provides a way to circumvent the checked exception mechanism and throw checked exceptions freely. If you run the above code, myMethod really throws an IOException without declaring it. How about that.

It’s not something I would recommend as a programming technique, though. The thing is: you can’t really catch them again. If you want to catch a checked exception from a piece of code, the compiler will give an error if it can’t prove that the code might throw that exception. And since the whole point of the hack above is that you can throw checked exceptions without declaring them, by definition, the compiler won’t allow you to catch them again. So it’s really more an odd curiosity than a useful programming technique. But then maybe that is the case for the whole mechanism of throwing type parameters.

Stuff

What is weirdest? Fálkarnir (I assume he’s an Icelandic country singer) doing a country version of flugufrelsarinn by sigur rós, or Jon Brion doing Creep by Radiohead in the style of Tom Waits?

Also, other videos of interest from YouTube: fun with corn starch, magnetic liquids and zero-g water.

Checked exceptions #3

As I’ve mentioned earlier I filed a feature request on sun’s developer network for allowing checked exception to be disabled. Unfortunately, they recently decided that this was not a big enough problem that it was worth the effort to solve it. To quote the evaluation:

The use cases against having to declare checked exceptions do not justify a change of this magnitude, at present.

Sadly, the evaluation completely misses the point. I have no problem with declaring exceptions when appropriate — it’s verbose but most everything is in Java and I’ve learned to live with that. Actually, I often declare unchecked exceptions even though I don’t have to because that can be really useful as documentation. What I do have a problem with is that checked exceptions often force you to choose between breaking encapsulation or handling exceptions locally, which is in many case the wrong place to handle them.need th

What it comes down to, really, is a matter of choice: some people want to be able to choose for themselves the best place to handle exceptions. Others believe that programmers can’t be trusted to make this decision. Me, I’m pro choice.

Back

After a few weeks in Mountain View I am now back in Denmark.

While I was in Mountain View I had a chance to hang out with Peter Ahé who told me about some of the interesting new developments in Java tools, especially in javac. I expect to write a few posts about that.

If your feed reader has experienced a small hiccup when reading this blog’s feed, that’s because the new version of blogger is now far enough along that I’ve been able to convert this blog to blogger beta. The most visible consequence of this is that posts can now be tagged with labels, the same way conversations can be tagged in gmail. Each label, for instance java, then gets its own index page. Not exactly a new idea but that doesn’t make it any less useful.