Search code examples
javaexceptionenums

Unhandled exception type Exception


This is a simplified class that describes my problem:

public class Main {

    enum Test{
        First(method()){ // Unhandled exception type Exception
            // ...
        };

        Test(Object obj){
            //...
        }
    }

    static Object method() throws Exception{
        // ...
        if (someCondition){
            throw new Exception();
        }

    }
}

Above someCondition depends on device and some situations and I can not decide in about it now, also as you can see, I do not want to catch Exception in method.


Solution

  • Yes. It is a compilation error.

    No. There is no special syntax to deal with this.

    I do not want to catch Exception in method.

    Unfortunately if you throw a checked exception, it has to be caught further up the call stack. That is a fundamental design principal for the Java language, and one that the compiler enforces strictly.

    In this case, there is no way to catch the checked exception. Hence, if you are going to call a method in enum constant parameter (as per your code), the method cannot throw a checked exception1.

    Here is a possible workaround, though this is probably a bad idea:

    public class Main {
    
        enum Test{
            First(methodCatchingException()){
                // ...
            };
    
            Test(Object obj){
                //...
            }
        }
    
        static Object method() throws Exception{
            // ...
            if (someCondition){
                throw new Exception();
            }
        }
    
        static Object methodCatchingException() {
            try {
                return method();
            } catch (Exception ex) {
                throw new SomeRuntimeException("the sky is falling!", ex);
            }
        }
    }
    

    Another way to look at this problem is to ask yourself what should happen with the exception if the compiler let you write that ... and an exception was thrown? Where would it go?

    • You can't catch it ... because the enum initialization is like a static initialization.
    • If the Java runtime completely ignored the thrown exception, that would be really bad.
    • If the Java runtime crashed, then the model of checked exceptions is broken.

    So, what this is saying to me is that the Java language design is right, the Java compiler is right ... and the real problem here is in your application design:

    • You should not be propagating a checked exception here. If an exception occurs in this context it is categorically NOT a recoverable error.

    • Maybe it is inadvisable to use an enum for this ... because of the potential for non-recoverable initialization errors.

    (Note that if this method call terminates due to an unchecked exception, it will turn it into an ExceptionInInitializerError. In addition, the JVM will mark the enum class as uninitializable, and will throw an NoClassDefFoundError if your application attempts to use it; e.g. via Class.forName(...).)


    I assume that Exception is used here for illustration purposes. It is a bad thing to declare methods as throws Exception or to throw new Exception(...)


    1 - I had a look at the JLS for something to back this up. As far as I can tell, the spec does not mention this situation. I'd have expected to see it listed in JLS 11.2.3. However, it is clear that a compiler cannot allow a checked exception to propagate at that point as it would "break" the model of how checked exceptions work.