본문 바로가기

Reading Record/이펙티브 코틀린

[이펙티브 코틀린] Item9. use를 사용하여 리소스를 닫아라

  • Closeable 인터페이스를 구한혀는 리소스는 레퍼런스가 없어질 때 가비지 컬렉터가 처리한다.

    • 자동 처리는 느리며 쉽게 처리되지 않아 close를 명시적으로 호출해주는 것이 좋다
  • java의 try with resource 같은 키워드가 없으므로 try finally로 처리가능하다

    • try finally로 처리할 시 try 예외 발생 후 finally 구문에서 예외가 발생하면 둘 중 하나의 예외만 전파된다
    • close 예외가 발생할 경우를 대비해 예외처리를 해주어야 한다.
  • kotlin은 위 불편을 해소하기 위해 use 함수를 제공한다

    • 코틀린의 확장함수로 제공

    • Closeable에 사용할 수 있다.

      @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
                    }
            }
        }
      }
    • 파일을 한줄씩 처리할 때 활용할 수 있는 useLines도 제공한다

      • 메모리에 한줄씩만 유지된다
      public inline fun <T> Reader.useLines(block: (Sequence<String>) -> T): T =
        buffered().use { block(it.lineSequence()) }