Search code examples
javaexceptiontry-catchreadabilitycatch-block

Several "ChildException" catch blocks versius one "Exception" catch block


What's better between several ChildException catch blocks and one Exception catch block? By better, I mean in a good-practices way.

To illustrate:

public static void main(String[] args) {
    System.out.println(Main.isNonsense1(null)); // false <- bad
    System.out.println(Main.isNonsense2(null)); // NullPointerException <- good
}

// More readable, less precise
public static boolean isNonsense1(String className) {
    try {
        Class.forName(className);
        String.class.getConstructor(String.class);
        className.getBytes("UTF-8");
        MessageDigest.getInstance("SHA-1").wait();
        return true;
    } catch (Exception e) {
        return false;
    }
}

// Less readable, more precise
public static boolean isNonsense2(String className) {
    try {
        Class.forName(className);
        String.class.getConstructor(String.class);
        className.getBytes("UTF-8");
        MessageDigest.getInstance("SHA-1").wait();
        return true;
    } catch (ClassNotFoundException e) {
        return false;
    } catch (NoSuchMethodException e) {
        return false;
    } catch (SecurityException e) {
        return false;
    } catch (UnsupportedEncodingException e) {
        return false;
    } catch (NoSuchAlgorithmException e) {
        return false;
    } catch (InterruptedException e) {
        return false;
    }
}

Solution

  • This is related to this question: Catch multiple exceptions at once?

    The answer there is good. The key is that if you catch Exception then you should handle each of the cases that you are aware of and throw all the rest. That is, simply catching Exception in your example and returning false would not be a good idea. You may inadvertently catch some exception you didn't mean to.

    Using your example, here is my suggested code:

    public static boolean isNonsense2(String className) {
        try {
            Class.forName(className);
            String.class.getConstructor(String.class);
            className.getBytes("UTF-8");
            MessageDigest.getInstance("SHA-1").wait();
            return true;
        } catch (Exception e) {
            if (e instanceof ClassNotFoundException
                    || e instanceof NoSuchMethodException
                    || e instanceof SecurityException
                    || e instanceof UnsupportedEncodingException
                    || e instanceof NoSuchAlgorithmException
                    || e instanceof InterruptedException) {
                return false;
            } else {
                throw e;
            }
        }
    }