3

When I throw checked exceptions from a method should I just declare the super class of the exceptions in the method signature or all the different types? If I have the following exceptions:

private class SuperException extends Exception {

}

private class SubExceptionOne extends SuperException {

}

private class SubExceptionTwo extends SuperException {

}

Should the method signature be:

 void confirmAccount() throws SubExceptionOne, SubExceptionTwo;

or

 void confirmAccount() throws SuperException;

In the last method signature, how do I tell other developers what exceptions that could be thrown from the method? If the different sub types need different handling?

mattias
  • 2,079
  • 3
  • 20
  • 27
LuckyLuke
  • 47,771
  • 85
  • 270
  • 434
  • 1
    It depends. By the same logic you can use declare `throws Exception`. How may subclasses are there? What information you want to convey. For example it's common to declare `throws IOException` rather than all the subclasses that might be thrown. – Boris the Spider Nov 09 '14 at 15:36
  • See also https://stackoverflow.com/questions/22610768/java-exception-handling-concept-why-do-compiler-allow-to-write-exceptions-in-th – Raedwald Jul 31 '17 at 08:37

3 Answers3

2

The interface should be as stable as possible. So probably Super. Many libraries use the "Super" strategy, because exception specs cause far more annoyance in maintainability than readability or safety they add. Even the IOException is a Super that nearly all Java library code uses instead of declaring more specific exceptions. (But when they do declare more specific exceptions, it's because the contract is that more general IOExceptions won't be thrown. Read on.)

You might list Sub1 and Sub2 if you really do want to say each of those exceptions can be thrown, but don't want to say that any derivative of Super can be thrown. Perhaps Sub1 is NumberCrunchException and your method calls crunchNumbers() and users of your method can be assured that's the only exception-ful thing your method does. In that case the specific strategy is better.

djechlin
  • 59,258
  • 35
  • 162
  • 290
  • If you declare the super class only, how should the callers catch the exception? Only by super type? Or do they need to know what sub types of the super type that can be thrown and then catch those that fit? I mean, callers may want to do different things depending on the exception that was thrown. Do you state this in the JavaDoc then if you only throw super type? – LuckyLuke Nov 09 '14 at 17:14
  • 2
    @LuckyLuke to answer your question, take a look at the new Java [`Files` API](https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#copy(java.io.InputStream,%20java.nio.file.Path,%20java.nio.file.CopyOption...)). Yes, you throw the superclass and describe all possible exceptions and error conditions in the Javadoc. The calling class can the decide what to do with the information. – Boris the Spider Nov 09 '14 at 17:40
  • @LuckyLuke what if your method really *can* throw a raw Super but can also throw a Sub1? The problem is then forced. However, if you make your Super abstract, I will say it's perfectly reasonable design to declare the specifics and catch the specifics... in which case why are you inheriting from Super at all? – djechlin Nov 09 '14 at 17:49
  • @djechlin Thank you for your answers. I have currently a ValidationException that is the super class of some more specific exceptions such as `DuplicateUsernameException`, `PasswordTooWeakException` and so on. These exceptions require different handling by the client. If I do it like the new files API it seems good. – LuckyLuke Nov 09 '14 at 18:05
1

If the different sub types need different handling, then definitely declare the two different exceptions. Never expect the developer using your method to guess that you are actually throwing different types of exceptions.

If you declare two distinct exceptions, and the user knows from the Javadoc that they are actually descendents of the same class, the user may choose to catch them both with a catch (SuperException e) rather than two individual catch clauses. But it depends on the user's choice.

If you don't declare them separately, your IDE is not going to add the appropriate @Throws to your Javadoc comment. And your Javadoc will therefore only indicate that you're throwing SuperException, which will leave the user in the dark. Solving this by just putting it in the text of the comment is not a real solution. If any tool is using reflection to determine what your method throws, it will not see the individual exceptions in the array returned from Method.getExceptionTypes().

If the functionality expected of the different exceptions is more or less the same and it's just a matter of how they will appear in the logs, it may be better to just use the parent exception, with different messages.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • No. The `catch` block will carry out `instanceof` checks automatically. The receiver will decide whether it needs to check for specific subtypes differently (for example, catch `FileNotFoundException` first then `IOExcpetion`). This is about convening information. – Boris the Spider Nov 09 '14 at 15:46
  • @BorisTheSpider. If he declared his method such that it throws IOException. How is the `catch` clause going to decide whether he threw a `FileNotFoundException` or an `EOFException`. The compiler does not detect any method that throws these particular exceptions within the `try`. – RealSkeptic Nov 09 '14 at 15:50
  • The receiver will first catch any specific exception they want to handle, then declare a catch to catch the superclass. The `try...catch` will see if the `catch` matches the thrown exception in order - so the compiler only requires that `IOException` is caught somewhere. If you have been using `instanceof` in catch blocks then something has gone very wrong... – Boris the Spider Nov 09 '14 at 15:52
  • @BoristheSpider OK, I removed the part about instanceof, but my opinion stands: you shouldn't leave the user guessing that you're actually throwing different types of exceptions. – RealSkeptic Nov 09 '14 at 16:00
  • I would argue that it's not for the throwing class to decide how an exception is handled. The whole point is that some general IO class might declare that it throws an `IOException`. A class that handles renaming files, for example, might throw a `FileNotFoundException`. – Boris the Spider Nov 09 '14 at 17:08
  • @BoristheSpider General IO classes actually throw an actual IOException, not a subclass thereof. If they decide to be general, they should actually throw the class they declared. If they decide to be particular and *allow* the user to distinguish between two different error state, then they should declare what they are throwing. – RealSkeptic Nov 09 '14 at 19:48
0

The throws clause is there to convey useful information to the calling method about what might go wrong during invocation of this method. That means that how specific you are will depend on how much information you want to convey; and that will be application-dependent.

For instance, declaring throws Exception is almost always a bad idea: the information this conveys is just "something might go wrong", which is too vague to be useful. But whether calling classes are going to need perfectly fine-grained information in the throws clause is something you need to decide by looking at your program. There's no set answer.

chiastic-security
  • 20,430
  • 4
  • 39
  • 67