[英]Is it safe to use try with resources in Java - does it check if the closeable is not null and does it catch exceptions while trying to close it
它是安全的使用Java的try with resources
在Android-不会检查是否可关闭不空,它捕获由抛出的异常close
,而试图关闭它?
如果我将其转换为:
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
}
至
try (FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel()) {
inChannel.transferTo(0, inChannel.size(), outChannel);
}
它会在尝试调用close
之前检查inChannel
和outChannel
是否不为null吗?
另外,在这里尝试使用资源是否安全:
try {
cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media.DATA},
MediaStore.Images.Media._ID + " =? ",
new String[]{"" + imageIdInMediaStore},
null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
return cursor.getString(0);
} else {
return "";
}
} catch (Exception e) {
return "";
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
cursor = null;
}
}
finally
块对!cursor.isClosed()
进行了重要检查-将try with resources
找出执行该操作的方法,还是应该保持不变?
最容易发现自己的方法是编写一个测试类,简单地告诉您有关它的信息:
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");
}
}
}
}
此类正常运行,没有错误,因此对您问题的答案是:
null
,所以在关闭阶段进行检查 close
时不会抛出异常,但必须由您自己捕获并处理 如果您稍微考虑一下,那是完全有意义的。 不支持null将使整个构造无用,即使忽略隐式关闭,也只是简单地忽略关闭是一件不好的事情。
编辑:上面的测试用例是结果,但是对于“真实”测试(例如,添加到您的源库中),您实际上应该检查是否已调用了autoclosesable中的close-method。
关于您的第二个问题:如果在某些情况下您不希望发生这种情况,则尝试将资源进行1:1更改不起作用,但是您可以执行以下操作:
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();
}
}
}
您的新代码将如下所示:
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 "";
}
我不确定isClosed
的检查是否确实必要,因此对于该特定示例,您可能不需要这种“ hack”,但对于不想关闭资源的其他示例,它仍然有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.