3

While trying to debug a weird issue where I knew an exception should have been thrown but was not, I found the following in the Java standard library's java.lang.ClassLoader class:

/**
 * Open for reading, a resource of the specified name from the search path
 * used to load classes.  This method locates the resource through the
 * system class loader (see {@link #getSystemClassLoader()}).
 *
 * @param  name
 *         The resource name
 *
 * @return  An input stream for reading the resource, or <tt>null</tt>
 *          if the resource could not be found
 *
 * @since  1.1
 */
public static InputStream getSystemResourceAsStream(String name) {
    URL url = getSystemResource(name);
    try {
        return url != null ? url.openStream() : null;
    } catch (IOException e) {
        return null;
    }
}

What reason would there be where the decision was made that this exception should not be thrown but instead silently consumed?

While discussing this with a coworker a possible option was that perhaps this function predated IOException and thus this was added to maintain backwards compatibility, however this method was added in Java 1.1, while IOException was added in 1.0.

This is a file operation so IOExceptions would not be out of place, so why would the makers of an exception based language choose returning null over passing up a thrown exception?

2 Answers2

4

This is unlikely to fail because:

getSystemResource() and therefore getSystemResourceAsStream() are using the System class loader.

It reads from local disk.

If it fails, we failed to read a file a jar or dir tree from the classpath.

IO Failures are unlikely, as we already started running from these jars, which have been verified ( and already read).

Failure to find the file is generally having the wrong filename , or a bad build of your code that doesn't include the resource. In these cases a null pointer will make your code crash fast in testing and your production code won't need to handle an IOException that only occurs if your build is screwed up.

2

The writers of the function get to define what "could not be found" includes. Here they include any IOExceptions thrown in the attempt as "could not be found". This simplifies the usage of this function, as the user only needs to check for null. A more modern library might have this return Option<InputStream>.

Notice how they don't try-catch getSystemResource, the documentation of that also specifies it returns null on failure.

Caleth
  • 12,190