Java also has chained exceptions, done manually

Tobias Mueller troplin at bluewin.ch
Fri Sep 7 23:15:03 UTC 2018


On Thursday, 6 September 2018 at 14:39:12 UTC, Andrei 
Alexandrescu wrote:
> Second, it does pay to keep abreast other languages. I had no 
> idea (and am quite ashamed of it) that Java also has chained 
> exceptions:
>
> https://www.geeksforgeeks.org/chained-exceptions-java/

Now I'm surprised... is there a language (except C++) that 
supports exceptions that does _not_ have it?
Java: getCause()
C#: InnerException
PHP: getPrevious()
...

> They implement them manually, i.e. the user who throws a new 
> exception would need to pass the existing exception (or 
> exception chain) as an argument to the new exception's 
> constructor. Otherwise, an exception thrown from a 
> catch/finally block obliterates the existing exception and 
> replaces it with the new one:
>
> https://stackoverflow.com/questions/3779285/exception-thrown-in-catch-and-finally-clause
>
> So chaining exceptions in Java is a nice complementary 
> mechanism to compensate for that loss in information: when you 
> throw, you have the chance to chain the current exception so it 
> doesn't get ignored. Because of that, D's chained exceptions 
> mechanism can be seen as an automated way of doing "the right 
> thing" in Java.
>
> We should study similarities and distinctions with Java's 
> mechanism and discuss them in our documentation.

I think chained exception in D is semantically very different 
from other languages like Java.

In languages like Java or C# the exception chain has nothing to 
do with saving exceptions that are thrown in finally blocks.
Instead the chain is used for a layer model. The "outer" 
exception is the higher level exception and the "inner" exception 
is the lower level cause of the higher level exception.

Often a low level exception is quite meaningless when thrown over 
multiple levels in the call stack.
For example, imagine a program that uses a configuration file. 
While parsing the configuration, a misformatted number is 
encountered.
If the NumberFormatException is propagated to the top level, it 
is basically useless for programmatic error handling.
This is much better:
ConfigurationException -> JsonParsingException -> 
NumberFormatException

The higher level exceptions are therefore directly caused by the 
lower level exception and always thrown _directly_ in the catch 
block where the lower level exception is catched and readily 
available. Not in a finally block and not indirectly in a 
function called from the catch block.
Manually passing the inner exception to the constructor of the 
outer exception is trivial and IMO the right thing, because it's 
probably not always wanted.

Now in D, chained exceptions work differently.
The first exception that is thrown is deemed the "important" 
exception and later exceptions are simply chained to it. A direct 
semantic connection between the exceptions is not possible at 
all, since the later exception has no knowledge about the first 
exception at all.
It also means that the order of the exceptions is reversed. The 
first exception is the "outer" exception which is the exact 
opposite of how it is meant in Java.

When handling an exception, it's not clear at all what those 
additional exceptions mean and how they should be handled.

Personally I find the Java/C# model much more useful.

---
Tobias


More information about the Digitalmars-d mailing list