Well, basically, throw e
will "rethrow" (pass) all original values (because the same Exception
instance, same object is will be used)- that will cause, it will pass also some code-flow- which maybe should be hidden, for example due the security reasons.
If you will re-create the exception, you will get - or better to say "you can get" - another stacktrace in the place using the new Exception instance
.
So, I would say, in this case , you have option to mask some data (Eg. you will log exceptions into a special log, but you will want to pass other diagnostic data to the end-user).
Let's check the following a bit to the details:
- I created one class as just only simple generator of Exceptions
- another class allows to rethrow or recreate exception
- afterwards, I am just printing the stacktrace and comparing results
Exception generator
public class ExceptionsThrow {
public static void throwNewException() throws Exception {
throw new Exception("originally thrown message");
}
}
Class for rethrow/ recreate exceptions
public class Exceptions {
public static void reThrowException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
//re-throw existing exception
throw e;
}
}
public static void reCreateNewException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
//recreation of the exception > new instance is thrown
throw new Exception(e);
}
}
}
Testing code example:
try {
Exceptions.reThrowException();
} catch (Exception e) {
System.out.println("1st RETHROW");
e.printStackTrace();
System.out.println("===========");
}
try {
Exceptions.reCreateNewException();
} catch (Exception e) {
System.out.println("2nd RECREATE");
e.printStackTrace();
System.out.println("===========");
}
And the output finally:
1st RETHROW
java.lang.Exception: originally thrown message
at test.main.stackoverflow.ExceptionsThrow.throwNewException(ExceptionsThrow.java:5)
at test.main.stackoverflow.Exceptions.reThrowException(Exceptions.java:7)
at test.main.MainTest.main(MainTest.java:110)
java.lang.Exception: java.lang.Exception: originally thrown message===========
2nd RECREATE
at test.main.stackoverflow.Exceptions.reCreateNewException(Exceptions.java:17)
at test.main.MainTest.main(MainTest.java:118)
Caused by: java.lang.Exception: originally thrown message
at test.main.stackoverflow.ExceptionsThrow.throwNewException(ExceptionsThrow.java:5)
at test.main.stackoverflow.Exceptions.reCreateNewException(Exceptions.java:15)
... 1 more
===========
In this case you can see mostly the same data, but also some additional, you can see the original message, because I have used the same Exception to built the new one - but its not necessary to create new Exception instance as this, so then you can mask original cause, or you don't need to expose the logic of the application, for instance let’s check one more example:
- I will take only the cause from the original exception, but it will override the data
- as you can see, a newly created exception doesn't contain the full stacktrace, as the origin
So:
public static void maskException() throws Exception {
try {
ExceptionsThrow.throwNewException();
} catch (Exception e) {
throw new Exception("I will dont tell you",e.getCause());
}
}
And the result:
===========
3rd mask
java.lang.Exception: I will don't tell you
at test.main.stackoverflow.Exceptions.maskException(Exceptions.java:25)
at test.main.MainTest.main(MainTest.java:126)
===========
So, I would say, recreate the exception with the same instance is a little bit pointless, but there can be cases once Exception transformation is needed (retype to another Exception type (then actually you should be also able to use java casting), or you want mask data
In the real world, I can remember the really often issue, when some web portals, handled exceptions in PHP scripts only by this case of printing, and then usually, when the connection with the database was not working correctly, connection strings (including database address and credentials in plaintext) were visible in the web browser, for example. :)