对Closeable的自动关闭处理,语法🍬

首先看一段示例代码:

 FileInputStream fis = null;
        try {
            fis = new FileInputStream("");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

一段基本操作,对文件流进行操作那么不论成功还是失败最好都要进行文件流的关闭。不过这样的代码确实挺样板的。我们看下java和kotlin对这中样本代码消除的语法糖实现。

1.java的实现

     try (FileInputStream fis = new FileInputStream("file_path");
             FileOutputStream fos = new FileOutputStream("file_path")) {
            byte[] bytes = new byte[1024];
            while ( fis.read(bytes) != -1) {
                fos.write(bytes);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

跟原来的写法唯一的区别就是将Closeable对象的声明是在try后的括号内,并且可以通过;来进行分割声明多个Closeable对象,在try包裹内的代码执行完后都会被自动close掉。

2.kotlin的实现

   val fis = FileInputStream("file_path")
    fis.use { 
        fis.read()
    }

通过使用use操作符来实现自动关闭Closeable对象,我们看一下use的源码:

@InlineOnly
@RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.")
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        when {
            apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
            this == null -> {}
            exception == null -> close()
            else ->
                try {
                    close()
                } catch (closeException: Throwable) {
                    // cause.addSuppressed(closeException) // ignored here
                }
        }
    }
}

一个高阶的内联函数,最终都是通过finally中进行关闭操作。