What’s new in Kotlin 1.7.0

1. The inline value of an inline class can be implemented through delegation

If you want to create a lightweight wrapper for a value or class instance, you need to implement all interface methods manually. Implementing via delegates solves this problem, but prior to 1.7.0 it didn't work in inline classes. This limitation has been removed, so now you can create lightweight wrappers that do not require memory allocation in most cases.

interface Bar {
    fun foo() = "foo"
}

@JvmInline
value class BarWrapper(val bar: Bar): Bar by bar

fun main() {
    val bw = BarWrapper(object: Bar {})
    println(bw.foo())
}

2. The underscore operator is used for type parameters

Kotlin 1.7.0 introduces the underscore operator _ for type parameters. This can be used to automatically infer type parameters when other types are specified:

abstract class SomeClass<T> {
    abstract fun execute(): T
}

class SomeImplementation : SomeClass<String>() {
    override fun execute(): String = "Test"
}

class OtherImplementation : SomeClass<Int>() {
    override fun execute(): Int = 42
}

object Runner {
    inline fun <reified S: SomeClass<T>, T> run(): T {
        return S::class.java.getDeclaredConstructor().newInstance().execute()
    }
}

fun main() {
    // T is inferred as String because SomeImplementation derives from SomeClass<String>
    val s = Runner.run<SomeImplementation, _>()
    assert(s == "Test")

    // T is inferred as Int because OtherImplementation derives from SomeClass<Int>
    val n = Runner.run<OtherImplementation, _>()
    assert(n == 42)
}

Type parameters can be inferred using the underscore operator anywhere in a variable list.

3. Stable version builder inference

Builder inference is a special type of type inference that is useful when calling generic builder functions. It helps the compiler to infer the type parameters of a call using type information from other calls within the lambda parameters.

Starting in 1.7.0, builder inference is automatically activated if regular type inference cannot obtain sufficient information about the type without specifying the -Xenable-builder-inference compiler option (introduced in 1.6.0).

Learn how to write custom generic builders.

4. Stable version opt-in requirements

As of version 1.7.0, Kotlin's opt-in requirements have been stabilized and no additional compiler configuration is required.

Prior to version 1.7.0, the Opt-in feature itself required the parameter -opt-in=kotlin.RequiresOptIn to avoid warnings. This is no longer necessary; however, you can still use the compiler parameter -opt-in to select other annotations for opt-in, targeting the entire module.

5. The stable version must not be empty type

In Kotlin 1.7.0, explicit non-null types have been promoted to a stability feature. They provide better interoperability when extending generic Java classes and interfaces.

You can use the new syntax T & Any to mark type parameters as explicitly non-null when using them. This syntactic form comes from the notation for intersection types, now constrained to have a type parameter with a nullable upper bound on the left side of & and a non-null Any on the right side:

fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
    // OK
    elvisLike<String>("", "").length
    // Error: 'null' cannot be a value of a non-null type
    elvisLike<String>("", null).length

    // OK
    elvisLike<String?>(null, "").length
    // Error: 'null' cannot be a value of a non-null type
    elvisLike<String?>(null, null).length
}

6. Standard library

In Kotlin 1.7.0, the standard library received a series of changes and improvements. They introduce new features, stabilize experimental features, and unify support for named capture groups in Native, JS, and the JVM:

Guess you like

Origin blog.csdn.net/old_land/article/details/130218138