Reputation: 513
public class SampleCloseable implements AutoCloseable {
private String name;
public SampleCloseable(String name){
this.name = name;
}
@Override
public void close() throws Exception {
System.out.println("closing: " + this.name);
}
}
and the main class
public class Main{
public static void main(String args[]) {
try(SampleCloseable sampleCloseable = new SampleCloseable("test1")){
System.out.println("im in a try block");
} catch (IOException e) {
System.out.println("IOException is never thrown");
} catch (Exception e) {
} finally{
System.out.println("finally");
}
}
}
But when i removed the throws exception on close() method inside SampleCloseable i am getting a compiler error saying that IOException is never thrown in the corresponding try block.
Upvotes: 4
Views: 195
Reputation: 31269
Your confusion may that around the fact the in Java 7, the exception that is [declared to be] thrown from the close
method is thrown inside the try block, so your catch block has to catch it as well.
Your close
method is declared to throw an Exception, so your catch
blocks have to catch that, or the method has to be declared to throw Exception
.
And since IOException
is a subclass of Exception
, you are of course allowed to try and catch that as well, as long as your also catch/declare Exception
itself.
See JLS 14.20.3.2:
The meaning of an extended try-with-resources statement [...] is given by the following translation to a basic try-with-resources statement (§14.20.3.1) nested inside a try-catch or try-finally or try-catch-finally statement.
Your code is effectively translated to the below. Although a bit longish, it should be clear from the below what's happening in your code.
public static void main(String args[]) {
try {
Throwable primaryEx = null ;
SampleCloseable sampleCloseable = new SampleCloseable("test1")
try {
System.out.println("im in a try block");
} catch (Throwable t) {
primaryEx = t;
throw t;
} finally {
if (sampleCloseable != null) {
if (primaryEx != null) {
try {
sampleCloseable.close();
} catch (Throwable suppressedExc) {
primaryEx.addSuppressed(suppressedExc);
}
} else {
sampleCloseable.close();
}
}
} catch (IOException e) {
System.out.println("IOException is never thrown");
} catch (Exception e) {
} finally{
System.out.println("finally");
}
}
Upvotes: 1
Reputation: 2798
Because you're throwing a generic Exception. Since an IOException inherits from Exception, it might be thrown by the close() method. The caller doesn't know that it doesn't actually get thrown. It only sees the method signature that says that it could.
In fact, the close() method is free to throw any Exception of any kind. Of course that's bad practice, you should specify what specific Exceptions you're throwing.
Upvotes: 10