在 Android 中使用 Java 的 try with resources
是否安全 - 它是否检查 closeable 是否不为 null 并在尝试关闭时捕获 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
是否不为空吗?
另外,在这里使用 try with resources 是否安全:
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
block 对 !cursor.isClosed()
进行重要检查 - 将尝试使用资源
找出如何做到这一点,还是我应该保持不变?
最佳答案
自己找出答案的最简单方法是编写一个测试类,简单地告诉您:
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 会使整个构造变得无用,简单地忽略关闭,即使它们是隐式完成的,也是一件非常糟糕的事情。
编辑:上面的测试用例是“真实”测试的结果,例如被添加到您的源库中,您实际上应该检查是否已调用自动关闭中的关闭方法。
关于您的第二个问题:如果在某些情况下您不希望关闭发生,则对 try-with-resources 的 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”,但它对于您不需要的其他示例仍然有效' 不想关闭资源。
关于java - 在 Java 中对资源使用 try 是否安全 - 它是否检查 closeable 是否不为 null 并在尝试关闭它时是否捕获异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47019545/