Exceptions just don't "throw" themselves. You must explicitly handle any checked exception thrown by a called method -- no matter where they occur. Anything you call that throws a checked exception must either be surrounded by a try catch block, or the method that is calling the sub-method must declare to throw the same type of exception. This does not apply to checked exceptions.
This means, that where you have
catch (Exception e) {
c.m1();
// or just throw it here
// throw new FileNotFoundException();
}
you must catch the checked exception thrown by m1
because main
does not declare that it throws anything.
With the finally
block on the try/catch, you still must handle any checked exception thrown by a called method -- even in the catch block. But in the case where you explicitly throw the checked exception with a finally block that explicitly throws a runtime exception, the compiler allows it because it knows for sure what the sequence of events will be -- in any case at any time.