java - 在 Java 中对资源使用 try 是否安全 - 它是否检查 closeable 是否不为 null 并在尝试关闭它时是否捕获异常

标签 java android

在 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 之前检查inChanneloutChannel 是否不为空吗?

另外,在这里使用 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/

相关文章:

java - 这段java代码是如何执行代码的?

java - 为什么 char[] 优于 String 作为密码?

java - 进行涉及 Java 的 RAW 套接字编程的最佳方法

java - 我应该如何在 Android Studio 3.0.1 中导出到 zip 文件

java - Firestore 分页适配器 - 如何知道查询是否返回 0 个结果

android - Ionic/AngularJS-如何解决错误 'Unfortunately, <app name> has stopped.'

java - 通过 Jenkins 在 Android Gradle 中设置构建属性

java - 当 spring 上下文关闭时停止 ConcurrentTaskScheduler

java - Apache POI 有效删除多列

java - 在 Recyclerview Viewholder 中,每 10 行(而不是 1 行)后标记多行