246

This may seem like a programming 101 question and I had thought I knew the answer but now find myself needing to double check. In this piece of code below, will the exception thrown in the first catch block then be caught by the general Exception catch block below?

try {
  // Do something
} catch(IOException e) {
  throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
  // Will the ApplicationException be caught here?
}

I always thought the answer would be no, but now I have some odd behaviour that could be caused by this. The answer is probably the same for most languages but I'm working in Java.

Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
roryf
  • 29,592
  • 16
  • 81
  • 103
  • 2
    Perhaps you could describe the "odd behaviour"? – Jeffrey L Whitledge Sep 27 '08 at 13:19
  • Are you sure the ApplicationException isn't being thrown elsewhere and propagating up to this block? – sblundy Sep 27 '08 at 14:42
  • I noticed this in my Eclipse IDE. It is tyring to force me to put the "throw new Exception" in a try block but I don't know why. I have done it in the past without doing that. I don't see why a try block would be required. Lots of examples on Google show people not needing a try block. Is it because I am throwing inside an if statement? – djangofan Feb 08 '13 at 23:38

9 Answers9

298

No, since the new throw is not in the try block directly.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Lets say if the code is like this try { } catch (Exception e){ System.err.println("In catch Exception: "+e.getClass()); }catch (IOException e){ System.err.println("In catch IOException: "+ e.getClass()); } and the code in try block generates IO Exception, Will it go to the immediate general Exception block or it will fly over to IOException catch block ? – sofs1 Aug 22 '16 at 23:25
  • 5
    @user3705478 The code won't compile, to avoid that kind of erroneous situation. In general, you're not allowed to have a catch for a subclass after a catch of its superclass in the same try block. – C. K. Young Aug 22 '16 at 23:32
  • Thanks. So I will get a compile time error, right? I will test it when I get home. – sofs1 Aug 22 '16 at 23:38
  • That depends @user3705478, if a `RuntimeException` is thrown from the `catch` block there will be no compilation error. – Randy the Dev Nov 30 '16 at 10:52
  • @AndrewDunn I don't think that's what user3705478's question is about, but rather, what happens if a parent exception `catch` clause is listed _before_ a child exception `catch` clause. My understanding is that Java disallows this, and it's caught at compile time. – C. K. Young Nov 30 '16 at 17:43
  • would it be caught again by a "parent catch block" if you nested one inside the other? – Nunchucks Nov 15 '18 at 18:56
84

No. It's very easy to check.

public class Catch {
    public static void main(String[] args) {
        try {
            throw new java.io.IOException();
        } catch (java.io.IOException exc) {
            System.err.println("In catch IOException: "+exc.getClass());
            throw new RuntimeException();
        } catch (Exception exc) {
            System.err.println("In catch Exception: "+exc.getClass());
        } finally {
            System.err.println("In finally");
        }
    }
}

Should print:

In catch IOException: class java.io.IOException
In finally
Exception in thread "main" java.lang.RuntimeException
        at Catch.main(Catch.java:8)

Technically that could have been a compiler bug, implementation dependent, unspecified behaviour, or something. However, the JLS is pretty well nailed down and the compilers are good enough for this sort of simple thing (generics corner case may be a different matter).

Also note, if you swap around the two catch blocks, it wont compile. The second catch would be completely unreachable.

Note the finally block always runs even if a catch block is executed (other than silly cases, such as infinite loops, attaching through the tools interface and killing the thread, rewriting bytecode, etc.).

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • 4
    The most obvious way to avoid a `finally` is, of course, to call `System.exit`. :-P – C. K. Young Sep 15 '11 at 13:25
  • 3
    @Chris Jester-Young `for(;;);` is shorter, contained within the language, doesn't introduce much in the way of side-effects and, for me, more obvious. – Tom Hawtin - tackline Sep 15 '11 at 20:50
  • 1
    `System.exit` is friendlier to the CPU! :-O But yes, okay, clearly this is a subjective criterion. Also, I didn't know you to be a code golfer. ;-) – C. K. Young Sep 15 '11 at 23:30
32

The Java Language Specification says in section 14.19.1:

If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:

  • If the run-time type of V is assignable to the Parameter of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed. If that block completes normally, then the try statement completes normally; if that block completes abruptly for any reason, then the try statement completes abruptly for the same reason.

Reference: http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#24134

In other words, the first enclosing catch that can handle the exception does, and if an exception is thrown out of that catch, that's not in the scope of any other catch for the original try, so they will not try to handle it.

One related and confusing thing to know is that in a try-[catch]-finally structure, a finally block may throw an exception and if so, any exception thrown by the try or catch block is lost. That can be confusing the first time you see it.

Community
  • 1
  • 1
Alex Miller
  • 69,183
  • 25
  • 122
  • 167
  • Just wanted to add that since Java 7 you may avoid that using `try`-with-resources. Then, if `try` AND `finally` both throw, `finally` is suppressed, but is also ADDED to exception from `try`. If `catch` throws as well, you're in no luck, unless you handle that yourself via 'addSuppressed' and adding the `try` exception - then you have all three. – LAFK 4Monica_banAI_modStrike Sep 16 '15 at 22:55
9

If you want to throw an exception from the catch block you must inform your method/class/etc. that it needs to throw said exception. Like so:

public void doStuff() throws MyException {
    try {
        //Stuff
    } catch(StuffException e) {
        throw new MyException();
    }
}

And now your compiler will not yell at you :)

Mastergeek
  • 429
  • 1
  • 6
  • 16
3

No -- As Chris Jester-Young said, it will be thrown up to the next try-catch in the hierarchy.

Ian P
  • 12,840
  • 6
  • 48
  • 70
2

As said above...
I would add that if you have trouble seeing what is going on, if you can't reproduce the issue in the debugger, you can add a trace before re-throwing the new exception (with the good old System.out.println at worse, with a good log system like log4j otherwise).

PhiLho
  • 40,535
  • 6
  • 96
  • 134
2

It won't be caught by the second catch block. Each Exception is caught only when inside a try block. You can nest tries though (not that it's a good idea generally):

try {
    doSomething();
} catch (IOException) {
   try {
       doSomething();
   } catch (IOException e) {
       throw new ApplicationException("Failed twice at doSomething" +
       e.toString());
   }          
} catch (Exception e) {
}
Vinko Vrsalovic
  • 330,807
  • 53
  • 334
  • 373
  • I wrote a similar code. But I'm not convinced. I want to call a Thread.sleep() in my catch block. But Thread.sleep throws itself an InterruptedException. Is it right (a best practice) to do it like you have shown in your example ? – riroo May 03 '17 at 11:06
1

No, since the catches all refer to the same try block, so throwing from within a catch block would be caught by an enclosing try block (probably in the method that called this one)

Uri
  • 88,451
  • 51
  • 221
  • 321
-9

Old post but "e" variable must be unique:

try {
  // Do something
} catch(IOException ioE) {
  throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
  // Will the ApplicationException be caught here?
}
Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
Ted K
  • 1
  • 1
  • 11
    This should be a comment and not an answer. It provides nothing in the way of addressing the actual question - it is just a critique of the OPs question. – Derek W Oct 13 '14 at 13:24