No, since the new throw is not in the try block directly.
No, since the new throw is not in the try block directly.
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.).
Videos
Based on reading your answer and seeing how you likely came up with it, I believe you think an "exception-in-progress" has "precedence". Keep in mind:
When an new exception is thrown in a catch block or finally block that will propagate out of that block, then the current exception will be aborted (and forgotten) as the new exception is propagated outward. The new exception starts unwinding up the stack just like any other exception, aborting out of the current block (the catch or finally block) and subject to any applicable catch or finally blocks along the way.
Note that applicable catch or finally blocks includes:
When a new exception is thrown in a catch block, the new exception is still subject to that catch's finally block, if any.
Now retrace the execution remembering that, whenever you hit throw, you should abort tracing the current exception and start tracing the new exception.
Exceptions in the finally block supersede exceptions in the catch block.
Java Language Specification
If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
Catch and re-throw.
try {
... same as before ...
} catch (ClassAlreadyRegisteredException | ProfessorNotFoundException e) {
throw e;
} catch (Exception e) {
// if there is any other error during the communication with the database,
// throw a generic IOException
throw new ClassIOException();
}
Alternatively, remember the exception to throw it later.
Exception fail = null;
try {
….
// save exception in place of existing throws
// for example:
fail = new ClassAlreadyRegisteredException();
…
} catch (Exception ex) {
...same as original...
}
if (fail != null) {
throw fail;
}
I use both techniques; the choice depends on what is simpler in any given situation. Neither is uncontestably better.
For the catch and re-throw method, you have to keep the list of caught-and-rethrown exceptions consistent with the exceptions you actually throw from within the try-clause. In larger cases, I'd avoid that problem by using an exception hierarchy, so I could catch the common base class.
For the save-and-throw method, you have to arrange control flow so that nothing significant is done after detecting the failure, since you don't have the immediate 'throw' command to exit the try-clause. Nevertheless there are cases where it is simple enough; the original example is one such.
Checked vs Unchecked Exceptions
It's totally acceptable to throw an exception in a catch block. A common use case is to take a checked Exception and throw a unchecked RuntimeException which would allow the exception bubble up to where it needs to be handled.
You'll want to use checked exceptions for use cases such as Connectivity/IO, SQL exceptions..
Handling Checked Exceptions
To answer your question, in most libraries that connect to the database, an checked IOException is thrown if there are any connectivity issues. For these cases, you can always specify this in the method signature public Class createClass() throws IOException
this specifies that any callers of createClass() has to fulfill the contract that the IOException is handled.
or
You can rethrow this as a RuntimeException
try {
...
} catch (IOException e) {
throw new RuntimeException(e); // <- send the original exception so you can preserve the exception and stacktrace.
}
This will essentially bubble up to STDOUT or whatever handler your framework specifies.
CAUTION:
However, catching an cover all Exception and throwing a more specific ClassIOException can have unintended consequences.
If you have a NullPointerException this will be captured by your catch (Exception e) block and rethrown as a ClassIOException
Doing this will corrupt the stacktrace and cause your error logs to be much more difficult to debug.
Understanding what constitutes an checked Exceptions.
Another tip is to consider what your Exception cases are.
If they are standard flow of the application, service, or business logic -- these may not be appropriate exceptions.
The ClassAlreadyRegisteredException and ProfessorNotFoundException may not be exceptional cases in your application... unless these are already specified by your professor.
Sometimes these can be thrown as RuntimeException if the situation calls for it.
Best Practices?
There are still many opinions on how exceptions are handled. So here are some rule of thumb questions I ask myself when working with exceptions
- Is the stacktrace preserved? Will I be able to trace back to the root Exception
- Is this common logic and represents an exceptional case that deviates from what my application provides?
- If I throw this exception, is it an absolute necessity for anything calling this method to handle this exceptional logic?
Hi
I'm not actually new to Java. but I want to make sure I'm following the correct practice
I have this method
public Response processRequest(XMLDocument document) {
try {
if (document.process().idFieldIsMissing())
throw new RuntimeException("error: id field missing from message");
if (document.process().importantHeaderIsMissing())
throw new RuntimeException("error: important header is missing");
if (more validation...)
throw new RuntimeException()...
return SuccessResponse("document is valid");
} catch (Exception e) {
return FailureResponse(e.getMessage());
}
}the basic gist is, I throw an exception in the method, and catch that exception in the very same method.
my reasoning is, I'd rather have one failure return statement in the catch block, then have multiple "return FailureResponse()" for each validation check.