The easiest way to find that out yourself is writing a test class simply telling you about it:
import junit.framework.TestCase; public class __Test_AutoClosable extends TestCase { public void testWithNull() throws Exception { try (TestClosable tc = getNull()) { assertNull("check existance of closable", tc); } } public void testNonNullWithoutException() throws Exception { try (TestClosable tc = getNotNull(false)) { assertNotNull("check existance of closable", tc); } } public void testNonNullWithException() throws Exception { try (TestClosable tc = getNotNull(true)) { assertNotNull("check existance of closable", tc); } catch(Exception e) { assertEquals("check message", "Dummy Exception", e.getMessage()); } } TestClosable getNull() { return null; } TestClosable getNotNull(boolean throwException) { return new TestClosable(throwException); } static class TestClosable implements AutoCloseable { private boolean throwException; TestClosable(boolean throwException) { this.throwException = throwException; } @Override public void close() throws Exception { if (throwException) { throw new Exception("Dummy Exception"); } } } }
This class runs through without errors, so the answers to your questions are:
- Yes,
null as response is possible, it is checked in the close-phase - Exceptions thrown on
close are not catched but must be catched and handled by yourself
If you think about this a bit, that makes complete sense. Not supporting null would draw the whole construct useless, simply ignoring closes, even if they are implicitly done, is a bad, bad thing.
Edit: The testcase above is the result but for a "real" test, e.g. being added to your source base, you should actually check if the close-method in the autoclosable has been called.
Concerning your second question: If there are cases where you don't want the close to happen, a 1:1-change to try-with-resources doesn't work but you can do something like this:
public class CursorClosable implements AutoClosable { private Cursor cursor; public CursorClosable(Cursor cursor) { this.cursor = cursor; } public Cursor getCursor() { return cursor; } @Override public void close() throws Exception { if (cursor != null && !cursor.isClosed()) { cursor.close(); } } }
Your new code would then look like this:
try (Cursor cursorac = new CursorClosable(context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media.DATA}, MediaStore.Images.Media._ID + " =? ", new String[]{"" + imageIdInMediaStore}, null)) { Cursor cursor = cursorac.getCursor(); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); return cursor.getString(0); } else { return ""; } } catch (Exception e) { return ""; }
I'm not sure if the check for isClosed is really necessary so maybe you don't need this kind of "hack" for this particular example but it's still valid for other examples where you don't want to close resources.
cursor.isClosed()is "an important check"? Just callcursor.close(). Theclose()method is required to be idempotent, so theisClosed()call is redundant. Callingclose()on an already closedcursordoes nothing. As the javadoc says: If the stream is already closed then invoking this method has no effect.