in following example, Eclipse does not ask me to add ' throws EmptyStackException'
public E pop() {
if (stack.isEmpty()) {
throw new EmptyStackException();
}
...
}
However, in following example, 'throws Exception' is required
public E pop() throws Exception {
if(stack.isEmpty()) {
throw new Exception();
...
}
Is there any specific rules on when should I add throws or not?
This is the difference between checked exceptions and unchecked exceptions.
A checked exception is part of a method signature, and is required to either be caught or declared to be thrown when the method is used. They are subclasses of Exception themselves.
Some examples include a particular constructor of Scanner, or more formally, Scanner#<init>(File file).
Checked exceptions are declared to be thrown typically because it is possible to recover from the exception. For instance, if you were to create a Scanner that read lines from a file, and the file didn't exist, what could you reasonably do besides ask them to re-specify the location?
An example:
Scanner sc = new Scanner(System.in);
boolean found = false;
String path = sc.nextLine();
while(!found) {
try {
sc = new Scanner(new File(path));
found = true;
} catch (FileNotFoundException e) {
System.out.println(path + " was not valid. Please try again.");
path = sc.nextLine();
}
}
An unchecked exception is not part of a method signature, and may be thrown for any particular reason. They are subclasses of RuntimeException.
One of the most common you'll encounter would be NullPointerException. This particular exception could occur in the most innocuous of ways, such as:
Integer i = null;
System.out.println(i + 2); // NPE on unboxing
It is not typically expected for one to be able to recover from the exception; in layman's terms, something has gone wrong with the assumptions made about the flow of code. That is to say, writing this is almost certainly a code smell:
Integer i = null;
try {
System.out.println(i + 2);
} catch(NullPointerException e) {
System.out.println("i was null!?");
}
Most modern frameworks will allow you to specify a specific state that your application enters when such an error occurs - if it's a web driven application, you can have those sorts of runtime exceptions handled as a 500.
There is also Error, which is a special case of unchecked exceptions - you should definitely not recover from this, since it's indicated that something has gone terribly, terribly wrong with the JVM.
For instance, this is something you don't want to see:
public void recurse() {
try {
recurse();
} catch (StackOverflowError e) {
System.out.println("We went in too deep.");
}
}
EmptyStackException extends RuntimeException which is an unchecked exception while Exception is a checked exception.
Java only obliges you to catch checked exceptions. You can read more about this here, here and here.
You don't need to declare/handle RuntimeExceptions in a method signature, but, You have to declare/handle Checked Exception, if the method throws it and not handled inside the method.
In your case, EmptyStackException is a RuntimeException, so, you don't need to handle/declare it in the method, but Exception is a checked one, so, you must need to either handle it or declare it in the method signature
Related
Let's say we have a constructor/method which throws IllegalArgumentExceptions on different occasions:
class MyClass {
MyClass(char char1, char char2) {
if(condition1 on char1 and char2) {
throw new IllegalArgumentException("condition1 failed");
}
if(different condition2 on char1 and char2) {
throw new IllegalArgumentException("condition2 failed");
}
...
}
}
If I wanted to construct an instance of MyClass with invalid arguments, how would I tell which exception was thrown?
try {
MyClass clazz = new MyClass('a', 'a');
} catch (IllegalArgumentException e) {
// which one?
}
An ugly solution would be checking the detail message, or in IllegalArgumentException's case, checking the provided cause, or using different types of exception (which doesn't seem appropriate in e.g. a parsing method). Is there a general solution to this problem?
you could write you own specific exceptions for both cases and thereby extend illegalArgumentException
edit: as Alex Shesterov already stated
You can check e.getMessage() in your catch block.
Consider the following code:
public Object getClone(Cloneable a) throws TotallyFooException {
if (a == null) {
throw new TotallyFooException();
}
else {
try {
return a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
//cant be reached, in for syntax
return null;
}
The return null; is necessary since an exception may be caught, however in such a case since we already checked if it was null (and lets assume we know the class we are calling supports cloning) so we know the try statement will never fail.
Is it bad practice to put in the extra return statement at the end just to satisfy the syntax and avoid compile errors (with a comment explaining it will not be reached), or is there a better way to code something like this so that the extra return statement is unnecessary?
A clearer way without an extra return statement is as follows. I wouldn't catch CloneNotSupportedException either, but let it go to the caller.
if (a != null) {
try {
return a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
throw new TotallyFooException();
It's almost always possible to fiddle with the order to end up with a more straight-forward syntax than what you initially have.
It definitely can be reached. Note that you're only printing the stacktrace in the catch clause.
In the scenario where a != null and there will be an exception, the return null will be reached. You can remove that statement and replace it with throw new TotallyFooException();.
In general*, if null is a valid result of a method (i.e. the user expects it and it means something) then returning it as a signal for "data not found" or exception happened is not a good idea. Otherwise, I don't see any problem why you shouldn't return null.
Take for example the Scanner#ioException method:
Returns the IOException last thrown by this Scanner's underlying Readable. This method returns null if no such exception exists.
In this case, the returned value null has a clear meaning, when I use the method I can be sure that I got null only because there was no such exception and not because the method tried to do something and it failed.
*Note that sometimes you do want to return null even when the meaning is ambiguous. For example the HashMap#get:
A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null. The containsKey operation may be used to distinguish these two cases.
In this case null can indicate that the value null was found and returned, or that the hashmap doesn't contain the requested key.
Is it bad practice to put in the extra return statement at the end just to satisfy the syntax and avoid compile errors (with a comment explaining it will not be reached)
I think return null is bad practice for the terminus of an unreachable branch. It is better to throw a RuntimeException (AssertionError would also be acceptable) as to get to that line something has gone very wrong and the application is in an unknown state.
Most like this is (like above) because the developer has missed something (Objects can be none-null and un-cloneable).
I'd likely not use InternalError unless I'm very very sure that the code is unreachable (for example after a System.exit()) as it is more likely that I make a mistake than the VM.
I'd only use a custom exception (such as TotallyFooException) if getting to that "unreachable line" means the same thing as anywhere else you throw that exception.
You caught the CloneNotSupportedException which means your code can handle it. But after you catch it, you have literally no idea what to do when you reach the end of the function, which implies that you couldn't handle it. So you're right that it is a code smell in this case, and in my view means you should not have caught CloneNotSupportedException.
I would prefer to use Objects.requireNonNull() to check if the Parameter a is not null. So it's clear when you read the code that the parameter should not be null.
And to avoid checked Exceptions I would re throw the CloneNotSupportedException as a RuntimeException.
For both you could add nice text with the intention why this shouldn't happen or be the case.
public Object getClone(Object a) {
Objects.requireNonNull(a);
try {
return a.clone();
} catch (CloneNotSupportedException e) {
throw new IllegalArgumentException(e);
}
}
The examples above are valid and very Java. However, here's how I would address the OP's question on how to handle that return:
public Object getClone(Cloneable a) throws CloneNotSupportedException {
return a.clone();
}
There's no benefit for checking a to see if it is null. It's going to NPE. Printing a stack trace is also not helpful. The stack trace is the same regardless of where it is handled.
There is no benefit to junking up the code with unhelpful null tests and unhelpful exception handling. By removing the junk, the return issue is moot.
(Note that the OP included a bug in the exception handling; this is why the return was needed. The OP would not have gotten wrong the method I propose.)
In this sort of situation I would write
public Object getClone(SomeInterface a) throws TotallyFooException {
// Precondition: "a" should be null or should have a someMethod method that
// does not throw a SomeException.
if (a == null) {
throw new TotallyFooException() ; }
else {
try {
return a.someMethod(); }
catch (SomeException e) {
throw new IllegalArgumentException(e) ; } }
}
Interestingly you say that the "try statement will never fail", but you still took the trouble to write a statement e.printStackTrace(); that you claim will never be executed. Why?
Perhaps your belief is not that firmly held. That is good (in my opinion), since your belief is not based on the code you wrote, but rather on the expectation that your client will not violate the precondition. Better to program public methods defensively.
By the way, your code won't compile for me. You can't call a.clone() even if the type of a is Cloneable. At least Eclipse's compiler says so. Expression a.clone() gives error
The method clone() is undefined for the type Cloneable
What I would do for your specific case is
public Object getClone(PubliclyCloneable a) throws TotallyFooException {
if (a == null) {
throw new TotallyFooException(); }
else {
return a.clone(); }
}
Where PubliclyCloneable is defined by
interface PubliclyCloneable {
public Object clone() ;
}
Or, if you absolutely need the parameter type to be Cloneable, the following at least compiles.
public static Object getClone(Cloneable a) throws TotallyFooException {
// Precondition: "a" should be null or point to an object that can be cloned without
// throwing any checked exception.
if (a == null) {
throw new TotallyFooException(); }
else {
try {
return a.getClass().getMethod("clone").invoke(a) ; }
catch( IllegalAccessException e ) {
throw new AssertionError(null, e) ; }
catch( InvocationTargetException e ) {
Throwable t = e.getTargetException() ;
if( t instanceof Error ) {
// Unchecked exceptions are bubbled
throw (Error) t ; }
else if( t instanceof RuntimeException ) {
// Unchecked exceptions are bubbled
throw (RuntimeException) t ; }
else {
// Checked exceptions indicate a precondition violation.
throw new IllegalArgumentException(t) ; } }
catch( NoSuchMethodException e ) {
throw new AssertionError(null, e) ; } }
}
Is having a return statement just to satisfy syntax bad practice?
As others have mentioned, in your case this does not actually apply.
To answer the question, though, Lint type programs sure haven't figured it out! I have seen two different ones fight it out over this in a switch statement.
switch (var)
{
case A:
break;
default:
return;
break; // Unreachable code. Coding standard violation?
}
One complained that not having the break was a coding standard violation. The other complained that having it was one because it was unreachable code.
I noticed this because two different programmers kept re-checking the code in with the break added then removed then added then removed, depending on which code analyzer they ran that day.
If you end up in this situation, pick one and comment the anomaly, which is the good form you showed yourself. That's the best and most important takeaway.
It isn't 'just to satisfy syntax'. It is a semantic requirement of the language that every code path leads to a return or a throw. This code doesn't comply. If the exception is caught a following return is required.
No 'bad practice' about it, or about satisfying the compiler in general.
In any case, whether syntax or semantic, you don't have any choice about it.
I would rewrite this to have the return at the end. Pseudocode:
if a == null throw ...
// else not needed, if this is reached, a is not null
Object b
try {
b = a.clone
}
catch ...
return b
No one mentioned this yet so here goes:
public static final Object ERROR_OBJECT = ...
//...
public Object getClone(Cloneable a) throws TotallyFooException {
Object ret;
if (a == null)
throw new TotallyFooException();
//no need for else here
try {
ret = a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
//something went wrong! ERROR_OBJECT could also be null
ret = ERROR_OBJECT;
}
return ret;
}
I dislike return inside try blocks for that very reason.
The return null; is necessary since an exception may be caught,
however in such a case since we already checked if it was null (and
lets assume we know the class we are calling supports cloning) so we
know the try statement will never fail.
If you know details about the inputs involved in a way where you know the try statement can never fail, what is the point of having it? Avoid the try if you know for sure things are always going to succeed (though it is rare that you can be absolutely sure for the whole lifetime of your codebase).
In any case, the compiler unfortunately isn't a mind reader. It sees the function and its inputs, and given the information it has, it needs that return statement at the bottom as you have it.
Is it bad practice to put in the extra return statement at the end
just to satisfy the syntax and avoid compile errors (with a comment
explaining it will not be reached), or is there a better way to code
something like this so that the extra return statement is unnecessary?
Quite the opposite, I'd suggest it's good practice to avoid any compiler warnings, e.g., even if that costs another line of code. Don't worry too much about line count here. Establish the reliability of the function through testing and then move on. Just pretending you could omit the return statement, imagine coming back to that code a year later and then try to decide if that return statement at the bottom is going to cause more confusion than some comment detailing the minutia of why it was omitted because of assumptions you can make about the input parameters. Most likely the return statement is going to be easier to deal with.
That said, specifically about this part:
try {
return a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
...
//cant be reached, in for syntax
return null;
I think there's something slightly odd with the exception-handling mindset here. You generally want to swallow exceptions at a site where you have something meaningful you can do in response.
You can think of try/catch as a transaction mechanism. try making these changes, if they fail and we branch into the catch block, do this (whatever is in the catch block) in response as part of the rollback and recovery process.
In this case, merely printing a stacktrace and then being forced to return null isn't exactly a transaction/recovery mindset. The code transfers the error-handling responsibility to all the code calling getClone to manually check for failures. You might prefer to catch the CloneNotSupportedException and translate it into another, more meaningful form of exception and throw that, but you don't want to simply swallow the exception and return a null in this case since this is not like a transaction-recovery site.
You'll end up leaking the responsibilities to the callers to manually check and deal with failure that way, when throwing an exception would avoid this.
It's like if you load a file, that's the high-level transaction. You might have a try/catch there. During the process of trying to load a file, you might clone objects. If there's a failure anywhere in this high-level operation (loading the file), you typically want to throw exceptions all the way back to this top-level transaction try/catch block so that you can gracefully recover from a failure in loading a file (whether it's due to an error in cloning or anything else). So we generally don't want to just swallow up an exception in some granular place like this and then return a null, e.g., since that would defeat a lot of the value and purpose of exceptions. Instead we want to propagate exceptions all the way back to a site where we can meaningfully deal with it.
Your example is not ideal to illustrate your question as stated in the last paragraph:
Is it bad practice to put in the extra return statement at the end
just to satisfy the syntax and avoid compile errors (with a comment
explaining it will not be reached), or is there a better way to code
something like this so that the extra return statement is unnecessary?
A better example would be the implementation of clone itself:
public class A implements Cloneable {
public Object clone() {
try {
return super.clone() ;
} catch (CloneNotSupportedException e) {
throw new InternalError(e) ; // vm bug.
}
}
}
Here the catch clause should never be entered. Still the syntax either requires to throw something or return a value. Since returning something does not make sense, an InternalError is used to indicate a severe VM condition.
public class OfficeTimeXception {
public int inTime;
public int outTime;
public void anyXception() throws CoreHourXception, NormalHourException {
int k = outTime - inTime;
if (inTime > 11) {
throw new CoreHourXception(inTime - 11);
}
if (k < 8) {
throw new NormalHourException(8 + (inTime - outTime));
} else if (outTime < 16) {
throw new CoreHourXception(16 - outTime);
}
}
if my try & catch statement is
{test.inTime = 12;
test.outTime = 19;
try {
test.anyXception();
}
catch (CoreHourXception e) {
System.out.println("core hour exception by" + e.getTime()
+ " hours");
e.printStackTrace();
} catch (NormalHourException e) {
System.out.println("normal hour exception by" + e.getTime()
+ " hours");
e.printStackTrace();
}}
I need to catch both exceptions when both conditions fail....but Iam able to get only coreHourException even when both the conditions failed.
You can only throw one Exception at a time, and code execution immediately stops when you do that (the later validations are not run at all).
If you want to check for multiple errors and return all the results at once, you have to collect the validation errors in a Collection and return that Collection (for example by attaching it to a wrapper Exception).
For example
List<Exception> errors = new List<>();
if (errorConditionOne) errors.add(new CoreHourXception());
if (errorConditionTwo) errors.add(new SomeOtherException(123, "abc"));
if (!errors.isEmpty) throw new ValidationException(errors);
These objects that you put in the errors Collection do not have to be Exception objects themselves, they can be anything that you find convenient to convey the information.
Merge CoreHourXception and NormalHourException into an HoreException which reports which conditions are violated:
public class HourException extends Exception {
private boolean normalViolated_;
private boolean coreViolated_;
public HourException(String message, boolean normalViolated, boolean coreViolated) {
super(message);
normalViolated_ = normalViolated;
coreViolated_ = coreViolated;
}
public boolean isCoreViolated() {
return coreViolated_;
}
public boolean isNormalViolated() {
return normalViolated_;
}
}
This is similar to Stephen C's solution. But instead of storing multiple message strings (which cannot be evaluated easily by any exception handler), you explicitly store the information about the violated constraints.
I need to catch both exceptions when both conditions fail....
That is impossible in Java ... and every other programming language I've ever come across.
Basically, only one exception can be thrown and can propagate at a time, and therefore only one exception can be caught.
If you want your code to report all of the failures, then you need to do something like this:
Create an empty list of messages.
Check each condition, one at a time. If the condition "fails", then add an error message to the list.
When you have checked all of the conditions, see if the list is non-empty. If it is, then EITHER convert the list of messages to a string and throw an exception with that string as the message OR throw an exception with a list field, passing the list to the exception via a constructor argument.
You can then catch the exception, and deal with the (possibly) multiple error conditions it is reporting.
Cumbersome? Yes!
I am trying to make it clear of the difference between Throws in method signature and Throw Statements in Java.
Throws in method signature is as following:
public void aMethod() throws IOException{
FileReader f = new FileReader("notExist.txt");
}
Throw Statements is as following:
public void bMethod() {
throw new IOException();
}
From my understanding, a throws in method signature is a notification that the method may throw such an exception. throw statement is what actually throw a created object under according circumstances.
In that sense, throws in method signature should always appear if there exist a throw statement in the method.
However, the following code doesn't seem doing so. The code is from the library. My question is why it is happening? Am I understanding the concepts wrong?
This piece of code is a copy from java.util.linkedList. #author Josh Bloch
/**
* Returns the first element in this list.
*
* #return the first element in this list
* #throws NoSuchElementException if this list is empty
*/
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
Update on the answer:
update 1 : is above code the same as the following?
// as far as I know, it is the same as without throws
public E getFirst() throws NoSuchElementException {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
update 2 : For checked exception. Do I need to have "throws" in the signature? Yes.
// has to throw checked exception otherwise compile error
public String abc() throws IOException{
throw new IOException();
}
You are pretty much right on. Except for one thing I'll mention in a bit.
throws is as much a part of the method API as the name and the parameters. Clients know if they call that method, they need to handle that exception--by simply throwing it also or by catching it and handling it (which may in fact entail the throwing of another exception wrapping the original). throws is addressed at compile time.
throw is the actual act of letting the runtime know something bad happened--that the exceptional condition we were worried about has in fact taken place. So it needs to be dealt with at runtime.
But you weren't quite right when you said, "Throws in method signature should always appear if there exist a throw statement in the method." That is often true but not always. I could also call another method that throws an exception within my method, and if I don't catch it, my method needs to throw it. In that case, there is no explicit throw of the same exception by me.
The final point is that you only need to declare an exception in throws when the exception is a checked exception--meaning it is from the other side of the Exception class hierarchy from RuntimeException. Common checked exceptions are IOException and SQLException. Checked exceptions must be listed in the throws part of the method signature if you don't handle them yourself. Anything subclassing RuntimeException--like NoSuchElementException in your example and also the hated NullPointerException--is an unchecked exception and doesn't have to be caught or thrown or anything.
Typically, you use checked exceptions for recoverable problems (where the client knows what can happen and can gracefully handle the problem and move on) and unchecked exceptions for catastrophic problems (like can't connect to the database).
If you can get past all the AOP stuff, this is a great discussion of how you use checked and unchecked exceptions effectively.
Vidya provided great answer to your questions.
The most important words are "The final point is that you only need to declare an exception in throws when the exception is a checked exception"
Just to show you an example code what does this mean. Imagine that we would like to use FileOutputStream in order to pass some data. The function would look like this:
public void saveSomeData() throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("input.txt");
out = new FileOutputStream("output.txt");
int c;
while ((c = out.read() != -1) {
in.write(c);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Close in
if (in != null) {
in.close(); // <-- If something bad happens here it will cause runtime error!
}
// Close out
...
}
}
Now imagine, if you wouldn't provide throws IOException and something bad happens inside finally{} statement - it would cause an error.
RuntimeExceptions dont have to be handled in try-catch block so they dont have to be declared as thrown and NoSuchElementException is RuntimeException because it extends it.
throw attribute in method signature, like you correctly guessed, is a hint to the compiler that the method raises an exception that must be caught by the caller. This kind of exception, namely called checked exception is something that the caller MUST always catch or dispatch to its caller again. This is something at compiler level, the signature specifies which exception the method is able to throw: this enforces a try-catch or re-dispatch in the caller and a throw statement somewhere inside the method, is a constraint that the developer places to specify something about the method behavior.
On the other hand other exceptions, namely unchecked or runtime exceptions, (NoSucheElementException is one example) are exceptions which you are not forced to specify becuase they arise from different situations.
The conceptual difference is that checked exception are usually used to warn about exceptional situation which should be handled somehow (think about IOException) by the developer, while unchecked are real errors (like NullPointerException or like in your example NoSuchElementException)
I want to catch an exception, that is nested into another exception.
I'm doing it currently this way:
} catch (RemoteAccessException e) {
if (e != null && e.getCause() != null && e.getCause().getCause() != null) {
MyException etrp = (MyException) e.getCause().getCause();
...
} else {
throw new IllegalStateException("Error at calling service 'service'");
}
}
Is there a way to do this more efficient and elegant?
The ExceptionUtils#getRootCause() method can come in very handy in such situations.
There is no more elegant way of selectively "catching" nested exceptions. I suppose if you did this kind of nested exception catching a lot, you could possibly refactor the code into a common utility method. But it still won't be either elegant or efficient.
The elegant solution is to do away with the exception nesting. Either don't chain the exceptions in the first place, or (selectively) unwrap and rethrow the nested exceptions further up the stack.
Exceptions tend to be nested for 3 reasons:
You have decided that the details of the original exception are unlikely to be useful for the application's error recovery ... but you want to preserve them for diagnostic purposes.
You are implementing API methods that don't allow a specific checked exception but your code unavoidably throws that exception. A common workaround is to "smuggle" the checked exception inside an unchecked exception.
You are being lazy and turning a diverse set of unrelated exceptions into a single exception to avoid having lots of checked exceptions in your method signature1.
In the first case, if you now need to discriminate on the wrapped exceptions, then your initial assumptions were incorrect. The best solution is change method signatures so that you can get rid of the nesting.
In the second case, you probably should unwrap the exceptions as soon as control has passed the problematic API method.
In the third case, you should rethink your exception handling strategy; i.e. do it properly2.
1 - Indeed, one of the semi-legitimate reasons for doing this has gone away due to the introduction of the multi-exception catch syntax in Java 7.
2 - Don't change your API methods to throws Exception. That only makes things worse. You now have to either "handle" or propagate Exception each time you call the methods. It is a cancer ...
You should add some checks to see if e.getCause().getCause() is really a MyException. Otherwise this code will throw a ClassCastException. I would probably write this like:
} catch(RemoteAccessException e) {
if(e.getCause() != null && e.getCause().getCause() instanceof MyException) {
MyException ex = (MyException)e.getCause().getCause();
// Do further useful stuff
} else {
throw new IllegalStateException("...");
}
}
I just solved a problem like this by writing a simple utility method, which will check the entire caused-by chain.
/**
* Recursive method to determine whether an Exception passed is, or has a cause, that is a
* subclass or implementation of the Throwable provided.
*
* #param caught The Throwable to check
* #param isOfOrCausedBy The Throwable Class to look for
* #return true if 'caught' is of type 'isOfOrCausedBy' or has a cause that this applies to.
*/
private boolean isCausedBy(Throwable caught, Class<? extends Throwable> isOfOrCausedBy) {
if (caught == null) return false;
else if (isOfOrCausedBy.isAssignableFrom(caught.getClass())) return true;
else return isCausedBy(caught.getCause(), isOfOrCausedBy);
}
When you use it, you would just create a list of if's from most specific Exception to least specific, with a fallback else-clause:
try {
// Code to be executed
} catch (Exception e) {
if (isCausedBy(e, MyException.class)) {
// Handle MyException.class
} else if (isCausedBy(e, AnotherException.class)) {
// Handle AnotherException.class
} else {
throw new IllegalStateException("Error at calling service 'service'");
}
}
Alternative/Addition per requests in comments
If you want to use a similar method to get the Exception object of the class you're looking for, you can use something like this:
private Throwable getCausedByOfType(Throwable caught, Class<? extends Throwable> isOfOrCausedBy) {
if (caught == null) return null;
else if (isOfOrCausedBy.isAssignableFrom(caught.getClass())) return caught;
else return getCausedByOfType(caught.getCause(), isOfOrCausedBy);
}
This could be used in addition to isCausedBy() this way:
if (isCausedBy(e, MyException.class)) {
Throwable causedBy = getCausedByOfType(e, MyException.class);
System.err.println(causedBy.getMessage());
}
It can also used directly instead of isCausedBy(), although it's probably a matter of opinion whether this is more readable.
Throwable causedBy;
if ((causedBy = getCausedByOfType(e, IllegalAccessException.class)) != null) {
System.err.println(causedBy.getMessage());
}
I see no reason why you want exception handling to be efficient and elegant, I settle for effective. They're called Exceptions for a reason.
This code will be a maintenance nightmare. Can't you redesign the call stack to throw the Exception you are interested in? If it is important the method signatures should show it and not hide it wrapped in 2 other exceptions.
The first (e != null) is unnecessary.
And you can change the 3rd better to e.getCause().getCause() instanceof MyException)
You can do as below:
catch (RemoteAccessException e) {
int index = ExceptionUtils.indexOfThrowable(e, MyExcetption.class)
if (index != -1) {
//handleMyException
} else {
}
}
I doubt, but you can check with instanceof if the exception is of the correct type.
Edit: There should be a reason that the nested exception is wrapped, so you have to ask yourself what is the purpose of catching the nested one.
I suppose you could also use ExceptionUtils.throwableOfThrowable() as in here
If you are investigating that whether an exception is caused by a custom exception (e.g. MyException) you can iterate with a while-loop until you find an instance of MyException.
boolean isCausedByMyException(Throwable exception) {
do {
if (exception instanceof MyException) {
return true;
}
exception = exception.getCause();
} while (exception != null);
return false;
}