3

Why is the code

void methodThrowsException() /*throws  Exception*/{
    try {
      // throw new Exception();
    } catch (Exception e) {
      throw e;
    }
}

well compiled? AFAIK compiler doesn't analyse code for can it throw an exception or not. Here obvious throw e; will never run (due to commented // throw new Exception();), but why does compiler know this?

Norbert Bicsi
  • 1,562
  • 2
  • 19
  • 33
J.J. Beam
  • 2,612
  • 2
  • 26
  • 55

2 Answers2

3

The javac compiler really doesn't do much of optimisation. But simple dead code detections and optimisations are yet possible.

In your example: the compiler can easily detect that the try block is empty. Empty try blocks can't throw, so all catch block code is essentially dead.

So the compiler could go in and simple drop the whole try/catch altogether here. Then there is nothing left that could throw an exception.

Which, when we use javap is exactly what we find in bytecode:

  void methodThrowsException();
    Code:
       0: return

And yes, the other answer is fully correct: this only works this way because you are using Exception, a more specific (checked) subclass will lead to a compiler error.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
3

The compiler will detect specific checked exception that are not thrown e.g.

void methodThrowsException() {
    try {
    } catch (URISyntaxException e) {
        throw e;
    }
}

will result in compiler error:

exception java.net.URISyntaxException is never thrown in body of corresponding try statement

but it won't check runtime exceptions, or the exception hierarchy root types like Exception, Error, Throwable. This is explained in JLS 11.2.3. Exception Checking.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • Thank you very much for the information about compiler doesn't error on root types, it's very tricky... – J.J. Beam Feb 07 '19 at 13:11