My Question is why was it designed that the catch block is optional, when there is no way of getting around not having a catch?
Yes there is: Declare that the method throws the exception:
public static void nocatch() throws CustomException
{
try
{
throw new CustomException();
}
finally
{
}
}
try/finally
without catch
is to ensure that you clean up anything you need to clean up, even if you aren't handling the exception yourself. (Be sure not to allow any other exception to be thrown from within finally
, or you'll hide the primary exception.)
Here's an example to play with (live copy):
private static class CustomException extends Exception {
}
public static void main (String[] args) throws java.lang.Exception
{
try
{
System.out.println("Calling nocatch(false)");
nocatch(false);
}
catch (CustomException ce) {
System.out.println("Caught CustomException for false case");
}
try
{
System.out.println("Calling nocatch(true)");
nocatch(true);
}
catch (CustomException ce) {
System.out.println("Caught CustomException for true case");
}
}
public static void nocatch(boolean foo) throws CustomException
{
try
{
if (foo) {
System.out.println("Throwing");
throw new CustomException();
}
}
finally
{
System.out.println("In finally");
}
System.out.println("Reached outside the try/finally block");
}
Output:
Calling nocatch(false)
In finally
Reached outside the try/finally block
Calling nocatch(true)
Throwing
In finally
Caught CustomException for true case
As you can see, the finally
block's code runs regardless of whether an exception occurred, but the code after the try/finally
doesn't.
Re your follow-up asking why adding return
within the finally
makes the error go away:
try
{
throw new CustomException();
}
finally
{
return; // <=== Makes the compiler happy (but don't do it!)
}
Interesting edge case! It's because the code in the finally
block always runs, and so you'll always return rather than throw, hiding the exception that occurred. E.g., this is the sequence:
throw new CustomException()
throws the exception, which transfers control to the finally
block
Code in the finally
block issues a normal return from the method
This hides the fact the exception occurred; in effect, you've "handled" the exception (without actually handling it) via the finally
block. In general, this isn't a good idea; use catch
to handle exceptions, or declare them on the method so calling code can handle them.