Suppose there is a class such that:
public class Magic {
public static void main(String[] args){
boolean[] val = new boolean[0];
paradox(val);
}
private static boolean paradox(boolean[] arg) {
Container container = null;
try {
container = Container.getContainer(arg[0]);
return container.value;
} catch (UnsupportedOperationException e) {
e.printStackTrace();
return false;
} finally {
try {
container.sayHi();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
}
}
private static class Container{
private boolean value;
private Container(boolean value){
this.value = value;
}
private static Container getContainer(boolean value) throws UnsupportedOperationException{
return new Container(value);
}
private void sayHi(){
System.out.println("Hi!");
}
}
}
If this code is executed, there is a null pointer thrown on line with
container.sayHi();
container should, in fact, be null. Before the assignment can complete there is an ArrayIndexOutOfBoundException thrown when we call getContainer(). However, what happens to the ArrayIndexOutOfBoundException? Why do we go into finally{} after an unhandled exception?
edit: poor phrasing. question is why we go directly into finally{}. And what happens to ArrayIndexOutOfBoundException
Why do we go into finally{} after an unhandled exception?
We always go to finally after a block exits (successfully, after an exception handler, or after an unhandled exception). That's exactly what finally is for: a place to put code that will be run no matter what.
However, what happens to the ArrayIndexOutOfBoundException?
If you encounter a second exception in an exception handler or a finally block, then that second exception will be propagated and the original exception will be hidden.
If you want to preserve the original exception, you can manually attach it to the new exception via Throwable#addSuppressed (or the other way around, re-throw the original exception and attach the new one as suppressed).
There is a simple rule in Java: finally is always called.1
So what happens is this:
container = Container.getContainer(arg[0]);
This throws an ArrayIndexOutOfBoundException, which is uncaught. Before the exception bubbles, finally is called.
container.sayHi();
container == null so a NullPointerException is thrown, this shadows the original exception. As per the JLS §14.20.2
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice
... then
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
emphasis mine
1: except when System.exit is called or some other rare cirumstances.
Another surprise you may get when doing control flow operations inside finally block :
public static void main(String[] args) {
System.out.println(badFunction());
}
private static String badFunction() {
try {
throw new RuntimeException("Catch it!");
} finally {
return "Exception disappears";
}
}
Related
I am considering this from the 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).
I have a block as follows:
try {
.. do stuff that might throw RuntimeException ...
} finally {
try {
.. finally block stuff that might throw RuntimeException ...
} catch {
// what to do here???
}
}
Ideally, I would want any RuntimeException thrown in the finally block to escape, only if it would not cause a RuntimeException thrown in the main try block to be discarded.
Is there any way in Java for me to know whether the block that is associated with a finally block completed normally or not?
I'm guessing I could just set a boolean as the very last statement of the main try block (e.g., completedNormally = true. Is that the best way, or is there something better / more standard?
I believe the key is to not lose the original cause if any.
If we look at how try-with-resources behave:
private static class SomeAutoCloseableThing implements AutoCloseable {
#Override
public void close() {
throw new IllegalStateException("closing failed");
}
}
public static void main(String[] args) {
try (SomeAutoCloseableThing thing = new SomeAutoCloseableThing()) {
throw new IllegalStateException("running failed");
}
}
We end up with:
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:16)
Suppressed: java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:17)
This stack trace is great as we see both exceptions, i.e. we don't lose the running failed one.
Implementing this without try-with-resources, the wrong way:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
thing.close();
}
}
We end up with:
Exception in thread "main" java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:19)
We don't know that running failed occurred too as we broke the control flow, that's quite bad if you need to debug such a case.
Implementing this without try-with-resources, the right way (in my opinion), is to "log and forget" the exception that occurred in the finally block:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
try {
thing.close();
} catch (Exception e) {
LoggerFactory.getLogger(Main.class).error("An error occurred while closing SomeAutoCloseableThing", e);
}
}
}
We end up with:
17:10:20.030 [main] ERROR Main - An error occurred while closing SomeAutoCloseableThing
java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:10) ~[classes/:?]
at Main.main(Main.java:21) [classes/:?]
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:18)
Not as good as the try-with-resources approach, but at least we know what actually happened, nothing got lost.
I assume your finally block is doing cleanup. A good way to accomplish such cleanup is to create a class that implements AutoCloseable, so your code can place it in a try-with-resources statement:
class DoStuff
implements AutoCloseable {
public void doStuffThatMightThrowException() {
// ...
}
#Override
public void close() {
// do cleanup
}
}
(Notice that it does not need to be a public class. In fact, it probably shouldn’t be.)
The code in your example would then look like this:
try (DoStuff d = new DoStuff()) {
d.doStuffThatMightThrowException();
}
As for what happens if an exception is thrown during the cleanup: it becomes a suppressed exception. It won’t show up in a stack trace, but you can access it if you really want to (which you probably won’t).
I don't think there is an idiomatic solution to this problem, partly because you normally use finally to clean-up resources disregarding completely if the code that allocated the resource terminated normally or not.
For example you finally close a connection, but the transaction will be rolled back in the catch block or committed as a last statement of the code block wrapped in the try.
Concerning an throwable thrown inside the finally block, you should decide which exception is most important to pass on to the caller. You can ultimately create your own exception which holds reference to both exceptions, in that case you need to declare a variable initialized outside the try and set inside the catch.
For example, in the following code you either complete normally or throw an exception, while having tried a recovery (rolling back a transaction) and tried a clean-up in finally.
Either can fail and you wrap what you think is the most important data in the exception you finally throw.
private void foo() throws SQLException {
Throwable firstCause = null;
try {
conn.prepareStatement("...");
// ...
conn.commit();
} catch (SQLException e) {
firstCause = e;
conn.rollback();
throw e;
} finally {
try {
conn.close();
} catch (Exception e) {
throw new RuntimeException(firstCause);
// or
// throw new RuntimeException(e);
// or
// throw new MyException(e,firstCause);
}
}
}
You could capture the original exception and re-throw it from within finally block.
Code below does just that and the exception thrown out of the method below will have the stacktrace and the cause dictated by the outer RuntimeException.
private void testException() {
RuntimeException originalFailure = null;
try {
throw new RuntimeException("Main exception");
} catch (RuntimeException e) {
originalFailure = e;
} finally {
try {
throw new RuntimeException("Final exception");
} catch (RuntimeException e) {
if (originalFailure != null) {
throw originalFailure;
} else {
throw e; //OR do nothing
}
}
}
}
This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 4 years ago.
I am reviewing for OCP and I stumbled upon this scenario with Exceptions.
Typically, we encounter Suppressed Exceptions in try-with-resource. if the try block and close() method both throws an Exception, only the one in try block will be handled. The exception thrown in close() will be suppressed.
I am experimenting other ways to encounter suppressed exceptions. Running methodTwo() will just throw NullPointerException. It will be catched but it is not suppressed. What happened to IllegalArgumentException?
public class Main {
public static void main(String[] args) {
try {
methodTwo();
} catch (Exception e) {
e.printStackTrace();
for(Throwable t : e.getSuppressed()) {
System.out.println(t.getMessage());
}
}
}
static void methodTwo() {
try {
throw new IllegalArgumentException("Illegal Argument");
} finally {
throw new NullPointerException("Null Pointer");
}
}
}
as mentioned by comments, finally always executed if any exception or return happen. it is because of assurance of free resource like files and etc. if you don't return or throw new exception in finally, it return exception or value that set before.
you can change value that return in finally block too for example:
class A
{
public int value; // it is not good but only for test
}
public class Tester
{
public static void main(String[] args) {
System.out.println(method1().value); // print 10
}
private static A method1() {
A a = new A();
try
{
a.value = 5;
return a;
} finally
{
a.value = 10;
}
}
}
you can throw exception instead of throwing new value too and return value or last exception discarded. (but all of this is not good in programming design)
when you working with files, because there is nothing like destructor in java like c++ (although there is finally but it is different) you must using try finally (or for new way, use try-with-resource) to free resource obtained from system.
As explained here by #polygenelubricants
A try statement with a finally block is executed by first executing the try block. Then there is a choice:
If execution of the try block completes normally, [...]
If execution of the try block completes abruptly because of a throw of a value V, [...]
If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, [...]
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
For more detail , go to oracle documentation
This is something that's been bugging me for a while with regards to Program Flow.
I wanted to know if it's possible to catch an error from a Method in order to stop it from executing the Method that would normally follow it like the example bellow that I can't get to work.
public class MyClass {
public static void main(String[] args) {
// this method catches an exception and stops running
method01();
// this method will continue anyway which I don't want
method02();
};
};
I would normally have a static int variable that will initialize as 0 when the program is run and then if a method ever catches an exception it will increment that int and each method will only run if the int is 0.
This works but I was just wondering if I could replace the int shindig with exception handling.
Can you try:
try {
method01()
} catch (final Exception e) {
// do something
return; ///stop processing exit
}
the method01 will throw Exception:
private void method01() throws Exception {
// something
}
If you only want to terminate the whole program in case of an exception you just need to throw a RuntimeException without any further declaration. There are also specialized sub classes for explicit types of exceptions, like NullPointerException or IllegalStateException. See the "Direct Known Subclasses" section in the JavaDoc.
public class MyClass {
public static void main(String[] args) {
method01();
method02(); //method02 won't be called in case of an exception
}
private static void method01() {
// ...
if (true) // something goes wrong
throw new RuntimeException();
// further code won't be executed in case of an exception
}
private static void method02() {
System.out.println("method02 called");
}
}
Optionally it is possible to handle the exception with a try-catch-block:
public static void main(String[] args) {
try {
method01();
method02(); // method02 won't be called in case of an exception
} catch (Exception e) {
System.err.println("something went wrong");
}
}
// other code keeps unchanged...
If you want to enforce exception handling, you have to throw a subclass of Exception that is not derived from RuntimeException. But those exceptions have to be declared within the method Signature.
private static void method01() throws IOException {
throw new IOException();
}
You put method01 and method02 in to same try block:
public class MyClass {
public static void main(String[] args) {
try {
// This method catches an exception and stops running.
method01();
// This method will not continue if method01 have exception.
method02();
} catch (Exception e) {
e.printStackTrace();
}
}
// declare method01, method02, others...
}
Notice: You have mistakes at the end of code block ( }; }; )
Depends on what your method really does.
If your program should continue working also when an exception arise (e.g. NumberFormatException when parsing an input or in general a checked exception) a lot of people will suggest you to not use exception for flow control, but IMHO in very well defined cases (like NumberFormatException) the flow CAN be controlled by try catch statements and exceptions, it's really up to you.
A way to do so is to use the method returned parameter (also #Nikola answer works in this way, the point is to use the catch part of a try catch as flow control):
public class MyClass {
public static void main(String[] args) {
if(method01()) method02();
};
};
public boolean method01(){
try{
//some business
}catch(MyCheckedException e){
e.printStackTrace();
return false;
}
return true;
}
NB: You should use this approach only in well defined situations! If a file CAN be absent in a directory while opening it (checked FileNotFoundException), you COULD use this approach. If the file SHOULD be there and its not, the exception MUST stop the program.
I have a Java Program where I get data from a different source. some times while reading I see Exception and the program is exiting.
Mine is in a program that runs every 10minutes.
Public static void main(Strings[] args)
{
...readsource();
}
Private static void readsource() throws IOException
{
...
}
Issue:
I am able to get/See the Exception. But I want the program to continue
To that what is the best logic? I dont see try-catch-finally also is not addressing ..I want the program to continue even after seing the exception (I mean the next iteration should continue). This looks to be a Basic issue not sure how to address this...
Then you need to catch the exception, which you are currently not doing.
try {
readsource();
} catch (IOException e) {
// do something, never catch an exception and not do anything
}
//continue.
Note that exceptions usually indicate something is wrong. Unless you are going to do something about the exception, it might be better to fix the condition causing the exception....
You have to provide an error handler in your method, i.e. surround the call to readsource() with a try-catch block.
public static void main(Strings[] args)
{
try{
...readsource();
}
catch(IOException ioe){
//handle the error here,e.g don't do anything or simply log it
}
}
If you don't rethrow the exception in the catch block, execution will fall off the end of the catch block and continue as if there was no exception.
If you mean you'd like to recall the method wether an Exception was thrown or not just place this in a while loop i.e:
Public static void main(Strings[] args)
{
boolean run=true;
while(run) {
try {
System.out.print("Hello,");
readsource();
throw new IOException();
if(1==2)run=false;//stop the loop for whatever condition
} catch(IOException ioe) {
ioe.printStackTrace();
}
System.out.println(" world!");
}
}
}
Private static void readsource() throws IOException
{
...
}
Here's the code:
public class Exc {
int x = 2;
public void throwE(int p) throws Excp, Excp2 {
if(x==p) {
throw new Excp();
}
else if(x==(p+2)) {
throw new Excp2();
}
}
}
Here's the handler code:
public class tdExc {
public static void main(String[] args) {
Exc testObj = new Exc();
try {
testObj.throwE(0);
System.out.println("This will never be printed, so sad...");
} catch(Exception Excp) {
System.out.println("Caught ya!");
} catch(Exception Excp2) {
System.out.println("Caught ya! Again!!!!");
} finally {
System.out.println("This will always be printed!");
}
}
}
Excp and Excp2 both extends Exception and have similar code(nothing). Now I'm getting the error Exception has already been caught error at Excp2, regardless of whether I supply 2 or 0 to throwE method.
You're looking for:
try
{ }
catch(Excp excp)
{
log(excp);
}
catch(Excp2 excp2)
{
log(excp2);
}
finally
{ }
When you catch an exception, to specify the type of the exception, and the name of of its reference.
Your original code tried to catch Exception, which is the least specific exception, so you cannot catch anything after that.
When you are catching an exception, you have to specify what type of exception you are catching, this will allow you to better handle the exception that has occured. One thing that you have to keep in mind though, is that there is that there are specific and other more "wide purpose" exceptions.
For instance, NumberFormatException is more specific than Exception, since NumberFormatException will be thrown whenever you will try to parse a string into a number.
Thus, when having multiple catch statements, always put the most specific one on top, and the more generic ones at the end. If you put the more generic ones at the beginning, they will catch the exception before it can be passed to a more specific catch statement.
In your case, you are trying to catch the same exception twice, since you have two catch statements that try to catch the same exception.
Java dispatches to the catch() clauses based on the types of the exception: your clauses are both trying to catch an exception of type Exception, and give them the names Excp and Excp2:
public class tdExc {
public static void main(String[] args) {
Exc testObj = new Exc();
try {
testObj.throwE(0);
System.out.println("This will never be printed, so sad...");
} catch(Exception Excp) {
Shouldn't this be Excp e?
System.out.println("Caught ya!");
} catch(Exception Excp2) {
Shouldn't this be Excp2 e?
System.out.println("Caught ya! Again!!!!");
} finally {
System.out.println("This will always be printed!");
}
}
}
And, while it's unrelated, I think your earlier code would be easier for you to think about if you write it more like this:
public void throwE(boolean p) throws Excp, Excp2 {
if(p) {
throw new Excp();
} else {
throw new Excp2();
}
}
Call it with true or false as parameters.
I believe the exception can only be caught once with java. The first exception handler will process the error.
Please someone tel me if this is true for java :)