Kotlin 1.8.0 现已发布,有那些新特性?

Posted libin9iOak

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin 1.8.0 现已发布,有那些新特性?相关的知识,希望对你有一定的参考价值。

文章目录

Kotlin 1.8.0 版本现已发布,以下是其部分最大亮点:

  • JVM 的新实验性功能:递归复制或删除目录内容
  • 提升了 kotlin-reflect 性能
  • 新的-Xdebug编译器选项,提供更出色的调试体验
  • kotlin-stdlib-jdk7kotlin-stdlib-jdk8 合并为 kotlin-stdlib
  • 提升了 Objective-C/Swift 互操作性
  • 与 Gradle 7.3 兼容

有关完整的变更列表,请参阅Kotlin 1.8.0 最新变化

https://kotlinlang.org/docs/whatsnew18.html

已经 支持JVM 19 ,可完美的在JDK 17环境下开发程序

如何安装 Kotlin 1.8.0

如果您已经在使用IntelliJ IDEA(2021.3、2022.1、2022.2),IDE 会自动建议将 Kotlin 更新到 1.8.0。您也可以按照这些说明手动更新 IDE。

https://kotlinlang.org/docs/releases.html

对于 IntelliJ IDEA 2022.3,Kotlin 插件 1.8.0 将随即将推出的 IntelliJ IDEA 更新一起提供。你可以在 IntelliJ IDEA 2022.3 中把你的项目更新到 Kotlin 1.8.0,无需更新 IDE 插件。要在 IntelliJ IDEA 2022.3 中将现有项目迁移至 Kotlin 1.8.0,请将 Kotlin 版本改为1.8.0,然后重新导入 Gradle或 Maven 项目。

对于 android Studio Flamingo,Kotlin 插件 1.8.0 与最新 Canary 捆绑。对于 Android Studio Electric Eel,IDE 插件将随即将推出的 Android Studio 更新一起提供。

如果需要命令行编译器,请从GitHub 版本页面下载。
https://github.com/JetBrains/kotlin/releases/tag/v1.8.0

如果您遇到任何问题

  • 在Slack上获取帮助。

https://kotlinlang.slack.com/

  • 向我们的问题跟踪器YouTrack报告问题。

https://youtrack.jetbrains.com/issues/KT

更多文章和视频

YouTrack 上的最佳问题报告者

Adam(7 个问题)、pyos(5 个问题)、Ting-Yuan Huang(5 个问题)、Jinseong Jeon(4 个问题)、Efeturi Money(3 个问题)、Anton Keks(3 个问题)、wrongwrong(3 个问题)、Michael Bailey(3 个问题)、Guozheng Yuan(2 个问题)、jimgoog(2 个问题)、Nikita Nazarov(2 个问题)、Troels Lund(2 个问题)、liutikas(2 个问题)、Artyom Krivolapov(2 个问题)、Steven Schäfer(2 个问题)、Фагим Садыков(2 个问题)、David Corrado(2 个问题)、Jørgen Svennevik Notland(2 个问题)、David Herman(2 个问题)、Cev Ing(2 个问题)。

外部贡献者

我们要感谢所有拉取请求被纳入此版本的贡献者:Jinseong Jeon、pyos、Hung Nguyen、Mads Ager、Kristoffer Andersen、Steven Schäfer、Rick Clephas、Troels Bjerre Lund、Tianyu Geng、Iven Krall、Jaebaek Seo、Jerome Prinet、Jiaxiang Chen、Anže Sodja、Aurimas、Ivan Gavrilovic、Johan Bay、Martynas Petuška、Xin Wang、mcpiroman、Ahmed El-Helw, Aleksandr Kutashov、Aurimas Liutikas、Diego Gomez Olvera、Jason Parachoniak、Johan Bay、Kevin Bierhoff、Martin Bonnin、Matthew Haughton、Romain Guy、Shumaf Lovpache、Toshiaki Kameyama、Zac Sweers、aSemy、bennyhuo、soarex。

特别感谢我们的 EAP Champions

他们报告了问题并帮助我们稳定了 Kotlin 1.8.0 版本:

  • Zac Sweers
  • Alexander Nozik
  • Ahmed Moussa
  • Ankush Gupta

文章来源: https://mp.weixin.qq.com/s/z6mvC1Gc55b9XXWwE_uX-Q

结语

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。

Kotlin 1.6 正式发布,都有哪些新特性?

11月16日,Kotlin 1.6 正式对外发布。接下来就一起看一下在这个版本中都有哪些新的语法特性

  1. 更安全的when语句(exhaustive when statements)
  2. 挂起函数类型可作父类 (suspending functions as supertypes )
  3. 普通函数转挂起函数(suspend conversion)
  4. Builder函数更加易用
  5. 递归泛型的类型推导
  6. 注解相关的一些优化

1. 更安全的 when 语句


Kotlin 的 when 关键字允许我们在 case 分支中写表达式或者语句。1.6 之前在 case 分支写语句时存在安全隐患:

// 定义枚举 
enum class Mode   ON, OFF 
val x: Mode = Mode.ON

// when表达式
val result = when(x) 
    Mode.ON -> 1 // case 中是一个表达式
    Mode.OFF -> 2


// when语句
when(x)  
    Mode.ON -> println("ON") // case 是一个语句
    Mode.OFF -> println("OFF")

下表说明了编译器针对 when 关键字的检查内容

x 的类型枚举、密封类/接口、Bool型等(可穷举类型)不可穷举类型
when表达式case 必须穷举所有分支,或者添加 else,否则编译出错Case 分支必须包含 else,否则编译出错
when语句case 可以不穷举所有分支,不会报错同上

可见,当 x 是可穷举类型时,编译器对when表达式的检查比较严谨,如果 case 不能穷举所有分支或者缺少 else,编译器会报错如下:

ERROR: 'when' expression must be exhaustive, add necessary 'is TextMessage' branch or 'else' branch instead 

但编译器对于 when语句 的检查却不够严谨,即使没有穷举所有分支也不会报错,不利于开发者写出安全的代码:

// when语句
when(x)  // WARNING: [NON_EXHAUSTIVE_WHEN] 'when' expression on enum is recommended to be exhaustive, add 'OFF' branch or 'else' branch instead
    Mode.ON -> println("ON") // case 是一个语句

Kotlin 1.6 起,当你在 When语句 中是可穷举类型时必须处理所有分支,不能遗漏。考虑到历史代码可能很多,为了更平稳的过渡,1.6 对 when语句 中没有穷举的 case 会首先给出 Warning,从 1.7 开始 Warning 将变为 Error 要求开发者强制解决。


2. 挂起函数类型可作父类


Kotlin 中一个函数类型可以作为父类被继承。

class MyFun<T>(var param: P): () -> Result<T> 
    override fun invoke(): Result<T> 
        // 基于成员 param 自定义逻辑
    


fun <T> handle(handler: () -> Result<T>) 
    //...

Kotlin 代码中大量使用各种函数类型,许多方法都以函数类型作为参数。当你需要调用这些方法时,需要传入一个函数类型的实例。而当你想在实例中封装一些可复用的逻辑时,可以使用函数类型作为父类创建子类。

但是这种做法目前不适用于挂起函数,你无法继承一个 suspend 函数类型的父类

class C : suspend () -> Unit  // Error: Suspend function type is not allowed as supertypes 



C().startCoroutine(completion = object : Continuation<Unit> 
    override val context: CoroutineContext
        get() = TODO("Not yet implemented")

    override fun resumeWith(result: Result<Unit>) 
        TODO("Not yet implemented")
    
)

但是以挂起函数作为参数或者 recevier 的方法还挺多的,所以 Kotlin 1.5.30 在 Preveiw 中引入了此 feature,这次 1.6 将其 Stable。

class MyClickAction : suspend () -> Unit 
    override suspend fun invoke()  TODO() 


fun launchOnClick(action: suspend () -> Unit) 

如上,你可以现在可以像这样调用了 launchOnClick(MyClickAction())

需要注意普通函数类型作为父类是可以多继承的

class MyClickAction :  () -> Unit, (View) -> Unit 
    override fun invoke() 
        TODO("Not yet implemented")
    

    override fun invoke(p1: View) 
        TODO("Not yet implemented")
    

但是目前挂起函数作为父类不支持多继承,父类列表中,既不能出现多个 suspend 函数类型,也不能有普通函数类型和suspend函数类型共存。


3. 普通函数转挂起函数


这个 feature 也是与函数类型有关。

Kotlin 中为一个普通函数添加 suspend 是无害的,虽然编译器会提示你没必要这么做。当一个函数签名有一个 suspend 函数类型参数,但是也允许你传入一个普通函数,在某些场景下是非常方便的。

//combine 的 transform 参数是一个 suspend 函数
public fun <T1, T2, R> combine(
    flow: Flow<T1>, flow2: Flow<T2>, 
    transform: suspend (a: T1, b: T2) -> R): Flow<R>
     = flow.combine(flow2, transform)


suspend fun before4_1() 
    combine(
        flowA, flowB
    )  a, b ->
        a to b
    .collect  (a: Int, b: Int) ->
        println("$a and $b")
    

如上述代码所示,flowcombine 方法其参数 transform 类型是一个 suspend 函数,我们希望再次完成一个 Pair 的创建。这个简单的逻辑本无需使用 suspend ,但在 1.4 之前只能像上面这样写。

Kotlin 1.4 开始,普通函数的引用可以作为 suspend 函数传参,所以 1.4 之后可以改成下面的写法,代码更简洁:

suspend fun from1_4() 
    combine(
        flowA, flowB, ::Pair
    ).collect  (a: Int, b: Int) ->
        println("$a and $b")
    

1.4 之后仍然有一些场景中,普通函数不能直接转换为 suspend 函数使用

fun getSuspending(suspending: suspend () -> Unit) 

fun suspending() 

fun test(regular: () -> Unit) 
    getSuspending             // OK
    getSuspending(::suspending) // OK from 1.4
    getSuspending(regular)      // NG before 1.6

比如上面 getSuspending(regular) 会报错如下:

ERROR:The feature "suspend conversion" is disabled 

Kotlin 1.6 起,所有场景的普通函数类型都可以自动转换为 suspend 函数传参使用,不会再看到上述错误。


4. Builder 函数更加易用


我们在构建集合时会使用一些 Builder函数,比如 buildListbuildMap 之类。

@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
public inline fun <E> buildList(@BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> 
    contract  callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) 
    return buildListInternal(builderAction)


@kotlin.ExperimentalStdlibApi
val list = buildList<String> 
    add("a")
    add("b")

buildList 的实现中使用 @BuilderInterface 注解了 builderAction 这个 lambda 。这样可以在调用时 buildList 通过 builderAction 内部的方法调用智能推导出泛型参数的类型,从而减少模板代码

//<String> 可省略
val list = buildList 
    add("a")
    add("b")


//<String> 不可省略
val list = buildList<String> 
    add("a")
    add("b")
    val x = get(1)

但是 BuilderInterface 的类型推导限制比较多,比如 lambda 中调用的方法的签名要求比较严格,必须参数是泛型且返回值没有泛型,破坏了规则,类型推导失败了。所以上面代码中 lambda 有 get() 调用时,就必须清楚的标记泛型类型。这使得集合类的 builder 函数使用起来不那么灵活。

Kotlin 1.6 起 BuilderInterface 没有了类似限制,对我们来说最直观好处就是 Builder 函数内怎样的调用都不会受限制,使用更加自由

val list = buildList  
    add("a")
    add("b")
    set(1, null) //OK
    val x = get(1) //OK
    if (x != null) 
        removeAt(1) //OK
    


val map = buildMap  
    put("a", 1) //OK
    put("b", 1.1) //OK
    put("c", 2f) //OK

此 feature 在 1.5.30 也可以通过 添加 -Xunrestricted-builder-inference 编译器选项生效,1.6 已经是默认生效了。


5. 递归泛型的类型推导


这个 feature 我们平常需求比较少。

Java 或者 Kotlin 中我们可以像下面这样定义有递归关系的泛型,即泛型的上限是它本身

public class PostgreSQLContainer<SELF extends PostgreSQLContainer<SELF>> extends JdbcDatabaseContainer<SELF> 
    //...

这种情况下的类型推导比较困难,Kotlin 1.5.30 开始可以只基于泛型的上线进行类型推导。

// Before 1.5.30
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply 
  withDatabaseName("db")
  withUsername("user")
  withPassword("password")
  withInitScript("sql/schema.sql")


// With compiler option in 1.5.30 or by default starting with 1.6.0
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
  .withDatabaseName("db")
  .withUsername("user")
  .withPassword("password")
  .withInitScript("sql/schema.sql")

1.5.30 支持此 feature 需要添加 -Xself-upper-bound-inference 编译选项, 1.6 开始默认支持。


6. 注解相关的一些优化


Kotlin 1.6 中对注解进行了诸多优化,在编译器注解处理过程中将发挥作用

支持注解的实例化

annotation class InfoMarker(val info: String)
fun processInfo(marker: InfoMarker) = ...
fun main(args: Array<String>) 
    if (args.size != 0)
        processInfo(getAnnotationReflective(args))
    else
        processInfo(InfoMarker("default"))

Java 的注解本质是实现了 Annotation 的接口,可以被继承使用

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaClassAnno 
  String[] value();


public interface JavaClassAnno extends Annotation
    //...


class MyAnnotation implements JavaClassAnno  // <--- works in Java
 //...

但是在 Kotlin 中无法继承使用,这导致有一些接受注解类的 API 在 Kotlin 侧无法调用。

class MyAnnotationLiteral : JavaClassAnno  // <--- doesn't work in Kotlin (annotation can not be inherited)
  //...

注解类可以实例化之后,可以调用接收注解类参数的 API,能够与 Java 代码进行更好地兼容

泛型参数可添加注解

@Target(AnnotationTarget.TYPE_PARAMETER)
annotation class BoxContent

class Box<@BoxContent T> 

Kotlin 1.6 之后可以为泛型参数添加注解,这将为 KAPT / KSP 等注解处理器中提供方便。

可重复的运行时注解

Jdk 1.8 引入了 @java.lang.annotation.Repetable 元注解,允许同一个注解被添加多次。 Kotlin 也相应地引入了 @kotlin.annotation.Repeatable ,不过 1.6之前只能注解 @Retention(RetentionPolicy.SOURCE) 的注解,当非 SOURCE 的注解出现多次时,会报错

ERROR: [NON_SOURCE_REPEATED_ANNOTATION] Repeatable annotations with non-SOURCE retention are not yet supported

此外,Kotlin 侧代码也不能使用 Java 的 @Repeatable 注解来注解多次。

Kotlin1.6 开始,取消了只能用在 SOURCE 类注解的限制,任何类型的注解都可以出现多次,而且 Kotlin 侧支持使用 Java 的 @Repeatable 注解

@Repeatable(AttributeList.class)
@Target(ElementType.TYPE)
@Retentioin(RetentionPolicy.RUNTIME) //虽然是 RUNTIME 注解
annotation class Attribute(val name: String)

@Attribute("attr1") //OK
@Attribute("attr2") //OK
class MyClass 

最后


上述介绍的是 Kotlin1.6 在语法方面的一些新特性,大部分在 1.5.30 中作为 preview 功能已经出现过,这次在 1.6 中进行了转正。除了新的语法特性,1.6 在各平台 Compiler 上有诸多新内容,我们在平日开发中接触不到本文就不介绍了。

更多内容参考:https://kotlinlang.org/docs/whatsnew16.html

以上是关于Kotlin 1.8.0 现已发布,有那些新特性?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 1.6 正式发布,都有哪些新特性?

Kotlin 1.6 正式发布,带来这些新特性

张勇发阿里云全员信:要求视客户信任为生命;苹果因不送充电器在美面临新集体诉讼;Kotlin 1.8.0 发布|极客头条

Kotlin 1.5 新特性:密封接口有啥用?

Kotlin 1.2 新特性

Kotlin 1.5新特性记录