0
import java.util.Scanner;
import static java.lang.System.out;

public class practice
{
    public static void main(String args[])
    {
        Scanner sc=new Scanner(System.in);
        int x=sc.nextInt();

        try //outer try
        {
            try //inner try
            {
                if(x==1)
                    throw new NullPointerException();
                else if(x==2)
                    throw new InterruptedException();
                else
                    throw new RuntimeException();
            }
            catch(RuntimeException e) //catch block 1
            {
                out.println("RuntimeException caught!");
            }
            catch(InterruptedException e) //catch block 2
            {
                out.println("InterruptedException caught!");
            }
            out.println("inner try ends");
            return;
        }
        catch(Exception e) //catch block 3
        {
            out.println("Exception caught!");
        }
        finally
        {
            out.println("from finally");
        }

        out.println("main ends"); //unreachable code?
    }
}

In the above code, an exception is always thrown from the inner try block. It is either a RuntimeException (unchecked Exception) or an InterruptedException (checked Exception) that is caught by catch block 1 or catch block 2.

Any unchecked exception generated (not predicted by the compiler) will however be caught by catch block 1. As a result, the catch block 3 never gets executed.

Moreover, the line out.println("main ends"); also never gets executed due to the return statement in the outer try block.

My interpretation is wrong, since the program compiled successfully.

Can someone please tell me when does catch block 1 or the line out.println("main ends"); get executed?

DoubtExpert
  • 71
  • 1
  • 10
  • in either case it will throw exception. and your `if-else` block is responsible for this – bananas Nov 25 '19 at 04:06
  • 1
    What would happen if `out.println("inner try ends");` threw a `RuntimeException`? – Dawood ibn Kareem Nov 25 '19 at 04:07
  • You knowing an exception must occur does not mean you compiler knows – Mad Physicist Nov 25 '19 at 04:09
  • Another popular example: `int x; for(int i = 0; i < 10; i++) { if(i == 0) x = 1; else x += 1; }`. Clearly `x` is always initialized here, but the compiler doesn't know that. – Mad Physicist Nov 25 '19 at 04:11
  • @MadPhysicist The compiler knows in some cases. In simple `if...else` construct, it can determine whether x is initialized or not. For example, `int x; int i=0; if(i==0) x=1; else x=2; x+=1;` – DoubtExpert Nov 25 '19 at 06:12
  • @DoubtExpert. My point is not that it knows it some cases, which it has to if it's going to enforce anything. My point is that there are cases where it doesn't, and that threshold isn't very complicated. – Mad Physicist Nov 25 '19 at 14:09
  • @MadPhysicist The code also involves a similar simple `if..else` construct. When the compiler can check whether `x` is initialized or not, why cannot it know whether exception is thrown, having going through the same construct? – DoubtExpert Dec 01 '19 at 17:31

1 Answers1

3

NullPointerException is a child of RuntimeException. So all "inner try" blocks ends with the return.

     out.println("inner try ends");
---> return;

All finally blocks are executed as the docs says:

The finally block always executes when the try block exits.

in this case, return ends the "outer try", and the finally is executed.

If you make your code simpler, you will note that the last print is unreachable:

public static void main(String args[]) {
    Scanner sc = new Scanner(System.in);
    int x = sc.nextInt();

    try {
        try {
            if (x == 1) {
                throw new NullPointerException();
            }
        } catch (NullPointerException e) {

        }

        return;
    } finally {
        out.println("from finally");
    }

    out.println("main ends");
}
Main.java:24: error: unreachable statement
    out.println("main ends");
    ^
UselesssCat
  • 2,248
  • 4
  • 20
  • 35