madbean

re: Java's checked exceptions were a mistake

03 Apr 2003

On Java's checked exceptions were a mistake (and here's what I would like to do about it), Rolf Waldhoff introduced a "tunneling Exception through RuntimeException" concept:

I've grown increasingly fond of this approach, and think I'll try to put something together in the Jakarta Commons sandbox for it.

I find checked exceptions painful for exactly the same reasons as Rod, but I don't personally think they were a mistake. I like the "defensive programming" style, and I don't mind being forced to be explicit about exceptions. The problem is with "middleware", of course: how does a lower-level communicate checked exceptions to the higher-level without the "middleware" getting in the way.

Generic Java (JSR14) does introduce a way to mitigate this problem. It's not a 100% solution, but it has it's place. Generics allows you to use an Exception as a type parameter; so you might re-define the UnaryPredicate in Rod's example like this:

interface UnaryPredicate<T, E extends Exception> {
    boolean test(T obj) throws E;
}

This says that UnaryPredicate has a method test() that takes an argument of (some) type T and may throw an exception of (some) type T. The select() method then gets implemented this way:

public static <T, E extends Exception>
Collection<T> select(Iterator<T> iter,
                     UnaryPredicate<T,E> pred,
                     Collection<T> col)
    throws E
{
    while(iter.hasNext()) {
        T obj = iter.next();
        if(pred.test(obj)) {
            col.add(obj);
        }
    }
    return col;
}

Is that scary enough? Generics is cool, but make no mistake -- Generics is complex. You would then use this method as follows:

class IsDirectory
   implements UnaryPredicate<String, URISyntaxException>
{
    public boolean test(String obj) throws URISyntaxException {
        URI uri = new URI(obj);
        File file = new File(uri);
        return file.isDirectory();
    }
}

...

Collection<String> allFiles = getListOfFiles();
Collection<String> directoriesOnly = new ArrayList<String>();

try {
    CollectionAlgorithms.select(allFiles.iterator(),
                                new IsDirectory(),
                                directoriesOnly);
} catch (URISyntaxException e) {
    // thrown when someObject isn't a valid URI
}

I think that's a neat bit of syntax in use, but not in declaration. That is, it's nice to use select(), but the implementation of select() is a bit of a mouthful.

  • Home
  • Blog