Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is catch block optional?

I have the following code

public static void nocatch()
{
    try
    {
        throw new Exception();
    }
    finally
    {

    }
}

Which gives the error

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
Unhandled exception type CustomException

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?


From finally()'s perspective, I understand that

finally should have atleast a try block, catch is optional. The point of finally blocks is to make sure stuff gets cleaned up whether an exception is thrown or not. As per the JLS

A finally clause ensures that the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block.


Edit:

By adding a return in the finally block, compiler does not give the error WHY?!

public static void nocatch()
{
    try
    {
        throw new Exception();
    }
    finally
    {
        return; //By adding this statement, the compiler error goes away! Please let me know why
    }
}
like image 822
codeMan Avatar asked Mar 04 '15 14:03

codeMan


1 Answers

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:

  1. throw new CustomException() throws the exception, which transfers control to the finally block

  2. 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.

like image 62
T.J. Crowder Avatar answered Oct 13 '22 08:10

T.J. Crowder