Reputation: 308
I wrote an example which depicts my issue. I have a simple exception:
public class TryToSpeakException extends RuntimeException {
public TryToSpeakException(String message) {
super(message);
}
}
Then I have a chain of methods that invoke each other one by one:
public class TryToSpeak {
public static void speakToPerson1() {
throw new TryToSpeakException("Person 1 don't wanna speak to anyone.");
}
public static void speakToPerson2() {
try {
speakToPerson1();
} catch (Exception e) {
System.out.println("speakToPerson2 caused exception");
e.printStackTrace();
}
}
public static void speakToPerson3() {
try {
speakToPerson2();
} catch (Exception e) {
System.out.println("speakToPerson3 caused exception");
e.printStackTrace();
}
}
static void keepSilentToPerson() {
System.out.println("Keeping silent to person 1");
}
public static void communicate() {
try {
speakToPerson3();
keepSilentToPerson(); // Why it reaches this part?
} catch (Exception e) {
System.out.println("Communication exception.");
e.printStackTrace();
}
}
public static void main(String[] args) {
communicate();
}
}
The method from the very 'bottom' throws an exception. In method communicate()
after invocation of method speakToPerson3()
the execution keeps going.
What i need - is to Stop execution, so that invocation of method keepSilentToPerson()
is never reached and gives me the message "Communication exception."
.
This is what i get in console now:
speakToPerson2 caused exception
exceptions.TryToSpeakException: Person 1 don't wanna speak to anyone.
at exceptions.TryToSpeak.speakToPerson1(TryToSpeak.java:7)
at exceptions.TryToSpeak.speakToPerson2(TryToSpeak.java:12)
at exceptions.TryToSpeak.speakToPerson3(TryToSpeak.java:22)
at exceptions.TryToSpeak.communicate(TryToSpeak.java:36)
at exceptions.TryToSpeak.main(TryToSpeak.java:46)
Keeping silent to person 1
But if i call speakToPerson2()
from my Main method like this:
public static void speakToPerson1() {
throw new TryToSpeakException("Person 1 don't wanna speak to anyone.");
}
public static void speakToPerson2() {
try {
speakToPerson1();
keepSilentToPerson();
} catch (Exception e) {
System.out.println("speakToPerson2 caused exception");
e.printStackTrace();
}
}
static void keepSilentToPerson() {
System.out.println("Keeping silent to person 1");
}
public static void main(String[] args) {
speakToPerson2();
}
I get an obvious result:
speakToPerson2 caused exception
exceptions.TryToSpeakException: Person 1 don't wanna speak to anyone.
at exceptions.TryToSpeak.speakToPerson1(TryToSpeak.java:7)
at exceptions.TryToSpeak.speakToPerson2(TryToSpeak.java:12)
at exceptions.TryToSpeak.main(TryToSpeak.java:26)
keepSilentToPerson()
is not reached.
What am i doing wrong?
Upvotes: 3
Views: 8194
Reputation: 1920
speakToPerson2()
is catching the Exception, but you want communicate()
to catch it too. Essentially, speakToPerson2()
is suppressing the exception, so no other method sees it.
What you need to do is rethrow it (in both speakToPerson2()
and speakToPerson3()
). This is known as propagating an exception.
I.e.:
public static void speakToPerson2() {
try {
speakToPerson1();
} catch (Exception e) {
System.out.println("speakToPerson2 caused exception");
e.printStackTrace();
throw e;
}
}
public static void speakToPerson3() {
try {
speakToPerson2();
} catch (Exception e) {
System.out.println("speakToPerson3 caused exception");
e.printStackTrace();
throw e;
}
}
Upvotes: 2
Reputation: 344
You need to propagate your Exceptions to the main class to completely stop the execution of a program.
In the case 1: All your exception will be handled by speakToPerson2
function.
In the case 2: Your exception occurs at the function call of speakToPerson1
, so the rest of your code will not execute.
So, inorder to stop the program from running you just have to propagate the exception, using throw
keyword, in the catch block of your exception.
Upvotes: 0
Reputation: 949
You need to understand exactly how try-catch
work. If any method in the try-catch throws an exception (one that extends/or is Exception in your example), the body of the try-catch will be interrupted to go into the catch
clause.
In your case, the method speakToPerson1
will throw a TryToSpeakException
. This exception will be forwarded one step above in the method call stack, the method speakToPerson2
in your case. Since the call to speakToPerson1
is surrounded with a try-catch
, the catch
clause is invoked and System.out.println("speakToPerson2 caused exception");
is executed. Now, the try
clause encloses two methods calls, namely speakToPerson1
and keepSilentToPerson
. However, since the first method throw the exception, the second is never reached and therefore keepSilentToPerson()
will never by called.
Finally, think about the catching of exceptions. If you catch an exception, you are saying that you are going to handle it, by recovering or rethrowing it. If you handle it without rethrowing it, it won't be forwarded to the upper level of your call stack. Beware of this technicality
Upvotes: 2
Reputation: 4088
You can throw the exception after catching it speakTo*
methods. This will stop execution of code in methods calling speakTo*
and their catch block will be executed.
catch (Exception e) {
System.out.println("speakToPerson2 caused exception");
e.printStackTrace();
throw e;
}
Upvotes: 0