I built something I don't really understand - I don't know how it works. I've familiarized myself with this multicatch explaination article.
Consider these two exceptions and code:
public class MyException1 extends Exception {
// constructors, etc
String getCustomValue();
}
public class MyException2 extends Exception {
// constructors, etc
String getCustomValue() { return "foo"; }
}
try {
//...
} catch (MyException1|MyException2 e) {
e.getCustomValue(); // won't work, as I expected
}
I won't be able to call getCustomValue()
, even though the method is the same, because inside Java the above try/catch
is supposed to actually be casting the MyException1/2
to Exception
(that's how I understood the docs).
However, if I introduce an interface like this:
public interface CustomValueGetter {
String getCustomValue();
}
public class MyException1 extends Exception implements CustomValueGetter /*...*/
public class MyException2 extends Exception implements CustomValueGetter /*...*/
and add it to both exceptions, Java is actually able to allow me to use that method. And then calling this is valid:
try {
//...
} catch (MyException1|MyException2 e) {
e.getCustomValue(); // does work
}
In short, my question is: what is actually happening here: (MyException1|MyException2 e)
.
What is e
?
Is the closest superclass chosen as the type of e
? This question asks about it and that's, supposedly, the answer. If so, then why is the interface CustomValueGetter "visible" when I access e? It shouldn't be if, in my case, e
is an Exception
.
And if not, if the real class is either MyException1
or MyException2
why am I not simply able to call the same method available for both of those classes?
Is e
an instance of a dynamically generated class which implements all common interfaces of both exceptions and is of the nearest common supperclass type?
Runtime exceptions are ignored at the time of compilation.
Checked Exceptions These are the exceptions that are checked at compile time.
Java allows you to catch multiple type exceptions in a single catch block. It was introduced in Java 7 and helps to optimize code. You can use vertical bar (|) to separate multiple exceptions in catch block.
Handling More Than One Type of Exception The catch clause specifies the types of exceptions that the block can handle, and each exception type is separated with a vertical bar ( | ). Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final .
As Ischuetze said, e is looking for the class or interface that both exceptions do share. In your first example in can´t find a a sharing class despite the Exception class hence it is only able to use the methodes provided by it.
Changing your example to this code will be able to compile again.
public class MyException12 extends Exception {
public String getCustomValue(){ return "boo"; };
}
public class MyException1 extends MyException12{
public String getCustomValue() { return "foo"; };
}
public class MyException2 extends MyException12{
// constructors, etc
public String getCustomValue() { return "foo"; };
}
As in your Example with the interface, the Exceptions notifies that both MyException1
and MyException2
have MyException12
and hence are able to use it´s functions.
Here is a SO question answering the whole problem and what the type of e will be.
a quote from the link in the answer:
Changing the handling of exception types affects the type system in two ways: in addition to the usual type checking performed on all types, exception types undergo an additional compile time analysis. For the purpose of type checking, a catch parameter declared with a disjunction has type lub(t1, t2, ...) (JLSv3 §15.12.2.7) where the ti are the exception types the catch clause is declared to handle. Informally, the lub (least upper bound) is the most specific supertype of the types in question. In the case of a multi-catch exception parameter, the least upper bound of the types in question always exists since the types of all the caught exceptions must be subclasses of Throwable. Therefore, Throwable is an upper bound of the types in question, but it may not be the least upper bound since some subclass of Throwable may be a superclass (and thereby also a supertype) of the types in question and the exception types in question may implement a common interface. (A lub can be an intersection type of a superclass and one or more interfaces.) For the purpose of exception checking (JLSv3 §11.2), a throw statement (JLSv3 §11.2.2) that rethrows a final or effectively final catch parameter is treated as throwing precisely those exception types that:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With