繁体   English   中英

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

[英]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之前检查inChanneloutChannel是否不为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM