Search code examples
javaexceptionlanguage-design

Why is it mandatory that there should be a possibility of exception throwing in a try to write a catch?


I was playing around with some exception programs and came across something which i am surprised i never encountered before.

import java.io.*;

class ExceptionTest
{
  public static void main(String[] args)
  {
    try
    {
      System.out.println("hello");
    }
    catch(IOException ioe)
    {
      System.err.println("ioexception was thrown!!");
    }
  }
}

this raises an compiler error:

ExceptionTest.java:10: exception java.io.IOException is never thrown in body of
corresponding try statement
catch(IOException ioe)
^
1 error

My question is why is it like that?

Why is the compiler worried about a piece of code it is sure it would never reach. It could have just been a warning instead of a full-fledged error. Afterall we could want to keep the catch block as a backup for some future changes we might make or maybe the programmer just forgot to remove it after some edits.

I know i know it saves us from unnecessary keystrokes etc. etc. But it shouldn't bother compiler that much to raise an error. Or is there some other reason for this??

Also an IOException catch block in the code produces an compiler error but an Exception catch block does not... why is that?? Thnx in advance!!


Solution

  • Because the Java designers thought the system should help in this way. It's the same situation as this:

    public class EarlyReturn {
        public void foo() {
    
            return;
    
            System.out.println("Hi");
        }
    }
    

    ...which also results in a compile-time error. Code which will never be run is a bad thing, and the compiler helps us by letting us know it will never run, and the designers felt it should be an error rather than a warning.

    You can change your code to catch Exception rather than IOException if you like, but although that would make the compiler let you do it, you'd still have code that would never be run (which, again, is a bad thing).

    Also an IOException catch block in the code produces an compiler error but an Exception catch block does not... why is that??

    IOException is a checked exception, and only checked exceptions are checked in this way (that's why they're called that). There are checked exceptions, unchecked exceptions (RuntimeException and its subclasses), and errors (Error and its subclasses). Technically, checked exceptions are all exceptions that aren't unchecked exceptions or errors (Section 11.1.1 of the JLS), but — this is a bit of a dark corner — not all checked exceptions are checked. Specifically, checked exceptions are checked unless they're Exception or a superclass of it. From Section 11.2.3 of the JLS:

    It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case that the try block corresponding to the catch clause can throw a checked exception class that is a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception.

    The entirety of Section 11 is probably worth a read. As you can guess, this is a part of Java that evolved a fair bit in the early days, resulting in this somewhat convoluted definition of what gets checked.