2

I read in a Java book, that "Java will not allow you to declare a catch block for a checked exception type that cannot potentially be thrown by the try class body".

That makes sense so far.

But now I am asking myself why this code does compile:

    try {
        throw new Exception();
    } catch (IOException e) {
    } catch (Exception e) {
    }

Java allows me to catch the IOException, but obviously it will never be thrown by the try-block.

Doesn't this example break the rule described in the Java book?

mrbela
  • 4,477
  • 9
  • 44
  • 79
  • Maybe obvious to you, but the compiler can only spend that much time on static analysis. Given the halting problem, it can never be perfect. Something like Findbugs may produce a warning. – Thilo Jun 13 '19 at 13:09
  • You may want to read about a similar thread regarding dead code detection: https://stackoverflow.com/questions/2141029/unreachable-code-error-vs-dead-code-warning-in-java-under-eclipse – Thilo Jun 13 '19 at 13:15
  • Also note that when you want the "compiler to be smarter", you have to come with an *exact* spec that describes what should be detected. Because you don't want the same Java code to compile on some Java compilers and not on others. – Thilo Jun 13 '19 at 13:19

2 Answers2

6

Java allows me to catch the IOException, but obviously it will never be thrown by the try-block.

Because Exception is more general than IOException so the compiler understand that Exception can also be IOException.

Here is a contre example of what will happen if you try NumberFormatException instead of Exception

try {
    throw new NumberFormatException();
} catch (IOException e) {  // fail
} catch (Exception e) {
}

It fail because NumberFormatException is not general than IOException.

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • But in my case, the only possible exception that is thrown is from the the type `Exception`. So, in my example, the compiler could be smarter and knows this fact. Or am I wrong? – mrbela Jun 13 '19 at 13:13
  • @mrbela the compiler is not that smart, and it has a logic to follow, the logic is if the exception catched is less global than the thrown exception the compiler will not bother it self and gives you a warning – Youcef LAIDANI Jun 13 '19 at 13:32
3

It is obvious to a programmer that reads this code, but i guess the compiler will deal with the throw statement the same way it would deal with a call to a method declared as throwing Exception, and in this case, the thrown exception could very well be an IOException.

Maurice Perry
  • 9,261
  • 2
  • 12
  • 24
  • That's the key point.. When Java tries to invoke a method that throws an `Exception`, it can clearly catch all subtypes of it.. But in my case, it is never possible to catch an `IOException`, because the only possible exception that is thrown is from the type `Exception` itself. So, it's a bit confusing that Java doesn't know that, isn't it? Or am I wrong? – mrbela Jun 13 '19 at 13:11
  • For the compiler, there is no difference if you call a method in that block or not. All it sees is that you have a block that `throws Exception`. So it has to assume it can be any subclass of that. It only looks at "signatures" here. – Thilo Jun 13 '19 at 13:12
  • @mrbela yes, the compiler is lazy and doesn't bother to distinguish the two cases; it could be done by memorising not only which classes of exceptions are thrown in a block, but whether or not it could also be a subclass. – Maurice Perry Jun 13 '19 at 13:15