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 :)
Related
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?
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;
}
}
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
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;
}
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.
This question already has answers here:
Exception Handling with Multiple catch block [duplicate]
(2 answers)
Can I catch multiple Java exceptions in the same catch clause?
(10 answers)
Closed 4 years ago.
i have below piece of code which in my spring boot applicatin. This piece of code does email validation,
class EmailValidation {
public static void validate(List<String> s){
try {
for (String address : s) {
if (s == null || s.indexOf("#") < 0) {
throw new InvalidEmailAddressException("Email address is invalid ");
}
new InternetAddress(s);
}
} catch(AddressException e){
LOGGER.Error("Please validate email addresses");
}
}
}
class InvalidEmailAddressException extends RuntimeException {
public InvalidEmailAddressException(String message) {
super(message)
}
}
My question is how do I catch InvalidEmailAddressException? How can i achieve it to handle the exception in this piece of code itself and how it will be handled by the caller?
Use the multi-catch block like so:
try {
stuff
} catch (AddressException | InvalidEmailAddressException ex) {
handle exception
}
There're 2 types of exceptions: checked, unchecked.
InvalidEmailAddressException extends RuntimeException which is unchecked exception that you shouldn't catch, so better extend it from Exception class.
As an alternative to SnakeyHips' answer, you can provide several catch blocks separately, like
try {
// do what you have to do here
} catch (AddressException) {
LOGGER.Error("AddressException thrown");
} catch (InvalidEmailAddressException ex) {
LOGGER.Error("InvalidEmailAddressException thrown");
}
Firstly I think it is not good practice to extend from RuntimeException, that exception means that program crashes, you should extend from Exception. My opinion you should read some more about exceptions in Java. If your method does not catch exception you should put in method signature that method throws specific exception, something like:
public static void validate(List s) throws InvalidEmailAddressException {
... }
Then make this one:
class InvalidEmailAddressException extends Exception{
public InvalidEmailAddressException(String message){
super(message)
}
And that catch method, about AddressException you do not have it definition here, and I think if you want this to be proceed to caller you should not catch it at all, just declare in throws.
SnakeyHips' answer is solid but be aware that you will not able to react differently to different exceptions.
try {
//your code
} catch (AddressException e1) {
//handle this exception
} catch (InvalidAdressException e2) {
//handle this exception
}
This will enable you to handle the exceptions differently. If you dont care about this you may aswell just catch the general Exception class:
try {
//your code
} catch (Exception e) {
//handle exception
}
Suppose, I have a method:
private void someMethod() {
try {
//Do something here
}
catch (NullPointerException ex) {
System.out.println("error");
}
}
Now, I want to use this method somewhere else:
private void newMethod() {
someMethod();
JOptionPane.showMessageDialog(null, "Exception didn't occur");
}
Now, I want that if exception occurs in someMethod(), then newMethod() will not advance further, I mean, the JOptionPane message will not be shown in this case.
What will be the best way to do that? I have found a way by throwing another NullPointerException in catch block of someMethod() and then handling that from newMethod(). The code below demonstrates that:
private void someMethod() {
try {
//Do something here
}
catch (NullPointerException ex) {
System.out.println("error");
throw new NullPointerException("error");
}
}
private void newMethod() {
try {
someMethod();
JOptionPane.showMessageDialog(null, "Exception didn't occur");
}
catch (NullPointerException ex) {
System.out.println("error");
}
}
But, by this method, I am facing some difficulties for other cases. I guess there are better ways to achieve that. Thanks anyway.
You don't need to handle the exception inside someMethod. Instead you can declare the exception in this method's throws clause (if it is a checked exception) and let newMethod handle it.
private void someMethod() throws SomeCheckedException {
//Do something here
}
In case of NullPointerException, you don't need to do above, as it is an unchecked exception. Don't catch it inside someMethod, instead have try-catch inside newMethod.
It is good practice if your function intend to throw exception make it part of function declaration. So recommendation is to change someMethod() to private void someMethod() throws <exception Name>.
Depends on your requirement you can handle the exception in same method and throw another exception, or re throw same exception and handle it in another function.
In case you are re-throwing the same exception syntax is as follows:
private void someMethod() throws WhateverException {
try {
//Do something here
}
catch (WhateverException e) {
throw e;
}
}
Ok ... So I am learning about exceptions in java and i am currently at throw statements. I throw an exception of Exception class, and then re-throw it from the catch block again to handle it in the main function. But whenever i throw it as Exception class, i always get an Error in the catch block(where i re-throw it to be handled in main).But as soon as i change the thrown and caught Exceptions to some particular Exceptions like NullPointerException, it works!
Error Code:
class ThrowingExceptions {
static boolean enable3dRendering = false;
public static void main(String [] com) {
try {
renderWorld();
}
catch(Exception e) {
System.out.println("Rendering in 2d.");
}
}
static void renderWorld() {
try{
if(!enable3dRendering) {
System.out.println("3d rendering is disabled. Enable 3d mode to render.");
throw new Exception("3d mode Disabled.");
}
else {
System.out.println("The World is Empty!");
}
}
catch(Exception e) {
System.out.println("Please handle the error");
throw e; // It gives me an error here
}
}
}
Working Code:
class ThrowingExceptions {
static boolean enable3dRendering = false;
public static void main(String [] com) {
try {
renderWorld();
}
catch(NullPointerException e) {
System.out.println("Rendering in 2d.");
}
}
static void renderWorld() {
try{
if(!enable3dRendering) {
System.out.println("3d rendering is disabled. Enable 3d mode to render.");
throw new NullPointerException("3d mode Disabled.");
}
else {
System.out.println("The World is Empty!");
}
}
catch(NullPointerException e) {
System.out.println("Please handle the error");
throw e;
}
}
}
Why doesn't it work with Exception class and worked with its subclass??
Note :- The error i get in the error code is Unhandled exception type Exception
Runtime exceptions extend RuntimeException. They don’t have to be handled or declared.
They can be thrown by the programmer or by the JVM.
Checked exceptions have Exception in their hierarchy but not RuntimeException. They
must be handled or declared. They can be thrown by the programmer or by the JVM.
Errors extend the Error class. They are thrown by the JVM and should not be handled or
declared.
When method throws checked exception (1) you should handle or rethow it.
When method throws uncheked exception (2) you can handle or rethrow it, but it's not obligatory.
But whenever i throw it as Exception class, i always get an Error in
the catch block(where i re-throw it to be handled in main)
It means that your method is throwing checked exception which should be handled or rethrowed.
Handling:
public class Main {
public static void main(String[] args) {
try {
throw new Exception();
} catch (Exception e) {
try {
throw new Exception();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
Rethrowing:
public class Main {
public static void main(String[] args) throws Exception {
try {
throw new Exception();
} catch (Exception e) {
throw new Exception();
}
}
}
In your case:
// You declaring that the caller should handle exception
static void renderWorld() throws Exception {
try {
if(!enable3dRendering) {
System.out.println("3d rendering is disabled. Enable 3d mode to render.");
throw new Exception("3d mode Disabled.");
} else {
System.out.println("The World is Empty!");
}
} catch(Exception e) {
System.out.println("Please handle the error");
// You cannot just throw uncheked exception here
// You should handle it yourself or a caller should do it
throw e;
}
}
Changing
static void renderWorld() { ... }
to
static void renderWorld() throws Exception { ... }
should fix this. This is for the reason that runtime exception are unchecked exceptions.
Would recommend you to read about the Checked and Unchecked exception in details here - Java: checked vs unchecked exception explanation.
It's because they are several Exception classes which are inherited from the class Exception. Each can be throwed, catched but they divide into two groups:
Checked and unchecked exceptions:
An unchecked exception doesn't need to be handled and the
NullPointerException which you tried is from that group, so you don't need to care about it technically.
A checked exception need to be handled every time or it won't
compile, these exceptions are like IOException.
Since the base Exception Object can be checked and unchecked as well the compiler cares about that it should be handled everytime.
If you give it a try and change the NullPointerException to IOException it won't compile either cause it is a Checked Exception. So it was just random, that you exactly find one type of Exception which your code can be work without compile error.
For more info visit my blog post about it:
http://www.zoltanraffai.com/blog/?p=93
I tend to throw as many checked Exceptions up as possible: it declutters the code (and I regard checked Exceptions as a dubious aspect of Java). I tend to use them when "refining" code.. i.e. when it makes sense for the particular context.
This approach gets slightly complicated when overriding superclass/interface methods which don't throw the requisite Exception, and therefore I tend to do this:
#Override
public void close() {
try {
_close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
where _close is a private method which does all the business.
The problem when it comes to JUnit, if you actually want to test something where an exception is thrown by _close() is that the resulting RuntimeException seems to be handled by JUnit in an "unconditional" way: it seems always to stop the test with a failure message... even if you actually catch and deal with it in a try .. catch!
There is a sort of "workaround" for this which I've found (the CUT class closes all its closeableComponents when it is closed):
#Test (expected = RuntimeException.class)
public void errorFlagShouldBeSetIfAnyCloseablesThrowExceptionWhenCUTCloses() throws Exception {
Closeable spyCloseable = spy( new Closeable(){
#Override
public void close() throws IOException {
throw new IOException( "dummy" );
}});
spyCUT.addCloseableComponent( spyCloseable );
Exception blob = null;
try{
spyCUT.close();
}catch( Exception e ){
blob = e;
}
assertThat( spyCUT.getErrorFlag() ).isTrue();
if( blob != null ){
throw blob;
}
I.e. if you don't have this expected setting you always get a test failure (because of the RuntimeException "ignoring" the try .. catch). But in order to satisfy the expected you then have to rethrow the RuntimeException at the end of the test...
... is there any way of varying JUnit's handling of RuntimeExceptions?
Something must be wrong in your setup. JUnit does not have any such special handling for runtime exceptions.
I put together this MCVE; and it passes.
static class CUT {
void close(Closeable _close) {
try {
_close.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
#Test
public void test() throws Exception {
Closeable spyCloseable = Mockito.spy(new Closeable() {
#Override
public void close() throws IOException {
throw new IOException("dummy");
}
});
Exception blob = null;
try {
new CUT().close(spyCloseable);
fail("should have thrown");
} catch (Exception e) {
blob = e;
}
assertThat(blob.getMessage(), is("java.io.IOException: dummy"));
}
It is not exactly what you have up there; but "close enough" in my mind.
Long story short: your answer is coming from some other place. I suggest: do the same as I did: create a true mcve; and work your way from there!