try-with-resources: “use” extension function in Kotlin does not always work

后端 未结 4 1450
抹茶落季
抹茶落季 2021-01-11 10:51

I had some trouble expressing the Java\'s try-with-resources construct in Kotlin. In my understanding, every expression that is an instance of AutoClosable shou

相关标签:
4条回答
  • 2021-01-11 11:16

    Kotlin 1.1+ has a standard library that targets Java 8 to support Closeable resource pattern - kotlin-stdlib-jre8

    Gradle

    compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.1"
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:1.1.1"
    

    Maven

    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-stdlib</artifactId>
        <version>1.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-stdlib-jre8</artifactId>
        <version>1.1.1</version>
    </dependency>
    

    Sample

    val resource: AutoCloseable = getCloseableResource() 
    resource.use { r -> //play with r }
    
    0 讨论(0)
  • 2021-01-11 11:22

    Just make sure kotlin-stdlib-jdk7.jar in classpath, it's not added by default

    0 讨论(0)
  • 2021-01-11 11:23

    Kotlin targets Java 6 at the moment, so its standard library does not use the AutoCloseable interface. The use function only supports the Java 6 Closeable interface. See the issue tracker for reference.

    You can create a copy of the use function in your project and modify it to replace Closeable with AutoCloseable:

    public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
        var closed = false
        try {
            return block(this)
        } catch (e: Exception) {
            closed = true
            try {
                close()
            } catch (closeException: Exception) {
                e.addSuppressed(closeException)
            }
            throw e
        } finally {
            if (!closed) {
                close()
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-11 11:37

    For classes that do not support the "use" function, I have done the next homemade try-with-resources:

    inline fun <T:AutoCloseable,R> trywr(closeable: T, block: (T) -> R): R {
        try {
            return block(closeable);
        } finally {
            closeable.close()
        }
    }
    

    Then you can use it the next way:

    fun countEvents(sc: EventSearchCriteria?): Long {
        return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) {
            var rs = it.executeQuery()
            rs.next()
            rs.getLong(1)
        }
    }
    
    0 讨论(0)
提交回复
热议问题