United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 6534270 Support "suppresses" new keyword in method signatures
6534270 : Support "suppresses" new keyword in method signatures

Details
Type:
Enhancement
Submit Date:
2007-03-14
Status:
Open
Updated Date:
2011-02-16
Project Name:
JDK
Resolved Date:
Component:
specification
OS:
windows_xp
Sub-Component:
language
CPU:
x86
Priority:
P4
Resolution:
Unresolved
Affected Versions:
6
Targeted Versions:

Related Reports

Sub Tasks

Description
A DESCRIPTION OF THE REQUEST :
Method signatures in addition to "throws" section, should have a "suppresses" section that specifies which exceptions are suppressed by this method. For example if I have a method that does some I/O but doesn't want to declare IOException in its signature, it would look like this:

void doSomeWork() suppresses IOException
{
    RandomAccessFile raf = ...;
    raf.write(...);
    raf.close();
}

This would be equivalent to

void doSomeWork()
{
    try {
        RandomAccessFile raf = ...;
        raf.write(...);
        raf.close();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

Also

int getCount() suppresses IOException, MyAlgorithmException
        throws MyException
{
    int x = raf.length(); // RandomAccessFile.length()
    return myAlgorithm(x);
}

is equivalent to

int getCount() throws MyException
{
    try {
        int x = raf.length();
        return myAlgorithm(x);
    } catch (IOException e) {
        throw new RuntimeException(e);
    } catch (MyAlgorithmException e) {
        throw new RuntimeException(e);
    }
}


JUSTIFICATION :
It's not easy to say which exceptions should be declared as checked exceptions and which should be unchecked. In my opinion it depends on which abstraction layer you are coding in.

For example in low level libraries that directly use IO classes it makes sense for IOException to be checked. As soon as you go a tiny bit higher in abstraction layers it makes no sense to have IOException checked. It creates an awful coupling between the higher layer and the fact that the lower layer is actually doing IO (while a different implementation may keep everything in memory or database).

One way to avoid propagating the IOException statically in our code all way up to the application layer, is to catch it, log it and discard it (which I found very annoying; you have to have logging enabled and actually read through the logs to debug the code, etc.). A second way is to wrap it in another generic exception belonging to the higher layer and keep doing this between all the layers. Again very annoying because of all the messy code involved and in the end the client gets several exceptions wrapped in one another.

The reality is as soon as the exception leaves the layer it belongs to or at most the layer above, the code doesn't and shouldn't know much about the meaning of it. It has to be propagated all the way to the highest level and be dealt with there in a generic manner. So a third option is to wrap it in a RuntimeException and throw it. No one needs to care about this exception anymore and it's not discarded either. I found this to be much more elegant that the other two methods.

What's most annoying about IOException being checked is not that you have to deal with it after a call to RandomAccessFile.write(). It's having to deal with it because of calling MyStorage.store() which may or may not use RandomAccessFile. So we end up creating a StorageException and similar other ones just to wrap the exceptions of the lower layer, or even worse, we just log it and forget about it, or even more worse(!) just forget about it.

I found the proposed pattern so useful that I think supporting it at language level leads to much more elegant code for everyone.

                                    

Comments
EVALUATION

The Justification makes many excellent points. The proposal keeps suppressed exceptions explicit, which is a must, and has no VM impact. (Though it will reduce the maximum method size by a few bytes due to the inserted exception handlers.) I would support it.

Specifically:
- Any checked exception which can legally appear in a method's throws clause, can instead appear in a suppresses clause.
- It is legal to declare that a method throws exception type E and suppresses subtypes of E.
- It is a compile-time error to declare that a method suppresses exception type E and declare that it throws subtypes of E.
                                     
2007-03-16



Hardware and Software, Engineered to Work Together