Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java no-argument constructor: Throw impossible exception, or have empty catch block?

Is it better that a no-argument constructor throws an impossible exception or has an empty catch block? Let's say I have a class like this.

public class Foo {
    private int num;
    private String numString;

    public Foo() throws NumberFormatException {
        setNum("1");
    }

    public void setNum(String s) throws NumberFormatException {
        // In reality, complex code goes here
        num = Integer.parseInt(s);
        numString = s;
    }
}

The compiler forces the constructor to either throw NumberFormatException (which would never happen) or have a try/catch block. However, would it be correct to have an empty catch block, which is usually frowned upon?

public Foo() {
    try {
        setNum("1");
    } 
    catch (NumberFormatException e) { }
}

Please note that Foo would be a library class and others would use it, so having a no-argument constructor throw an impossible exception would be confusing. Also note that the real exception is a custom exception, not NumberFormatException, which might make things even more confusing for the library user, who might feel like they have to read up on the custom exception when it is not necessary.

like image 681
anomal Avatar asked Dec 07 '22 14:12

anomal


1 Answers

NumberFormatException is a RuntimeException, so you don't need to list it on your throws clause -- just pretend it's not there. That goes for both the method and the constructor.

Any subclass of RuntimeException (including RuntimeException itself) is an "unchecked exception," which means the compiler won't force you to check for it in a try/catch clause. In contrast, any Exception which is not a subclass of RuntimeException is called, easily enough, a checked exception.

If it were a checked exception (that is, not a subclass of RuntimeException), but you were sure that you could never trigger it, then it'd be safe to catch it. Rather than completely swallowing it, it'd be best to wrap it around an unchecked exception.

try {
    thisCodeCanNeverThrowAnIOException();
}
catch (IOException e) {
    throw new AssertionError(e); // juuust in case!
}

Now your code compiles, doesn't have a throws clause for an exception you never expect to be thrown, and yet will not hide a serious error if, by some bug or future change, that exception does end up getting thrown.

(Note to those reading the comments: I originally had in the code example throw new RuntimeException(e), but Stephen C and Peter Lawrey pointed out that, in Java 1.4.2 and newer, AssertionError is better).

like image 90
yshavit Avatar answered Apr 23 '23 16:04

yshavit