Issue
AFAIK, the standard try-with-resources
form
try(InputStream is= new ...){
... some reading from is
} catch (..){
... catching real problems
}
catch (IOException e) {
... if closing failed, do nothing - this clause is demanded by syntax
}
is equivalent to:
try{
InputStream is= new ...
... some reading from is
} catch (..){
... catching real problems
} finally {
try{
is.close();
} catch (IOException e) {
... if closing failed, do nothing
}
}
The first variant is more simple, of course. But I see the case when the second variant is absolutely OK, whereas the first becomes ununderstandable.
Imagine the situation, when you have got code, where the try(){}
appears in the function with throws IOExceptions
clause.
String readFromFile(...) throws IOException{
...
try(...){
...
}
}
The IOException in the second catch eats all IOExceptions, either connected to the attempt of closing or not. And does nothing. I suppose, that somewhere out of the method there is a piece of code that works with that IOException and does something noticeable. For example, logs the stack. So, local catches will be never reached. We are not interested in the second catch clause, but usually, we need some special reaction for the first one.
On the other hand, if we delete the closing catch(IOException e){}
clause, counting on the throws
in the method header, that absolutely uninteresting for us closing exception will be reacted to.
While we are catching the closing problems by IOException, I see no way out of the problem. And Eclipse java editor demands me to use this very exception for that clause!
How can I divide IOException appearing from closing from other IOExceptions, appearing in the try{} body?
Solution
I think Java is to blame for this one. The close() method should have thrown a different exception than IOException there is rarely anything the caller can do about it. Your only solution is to rewrap the IOExceptions you're interested in before rethrowing.
Usually what I do is I extract the entire content of the try-block to its own method where I can catch any IOExceptions and re-throw them as custom exceptions. I can then catch the remaining IOException by itself in the catch block.
public void foo() throws CustomException {
try (InputStream is= new ...) {
bar(is); //This catches internal IOExceptions and throws a CustomException
}
catch (IOException e) { //The close() exception
}
}
Answered By - Adam
Answer Checked By - Willingham (JavaFixing Volunteer)