Kotlin:2.0.0 的新特性

news2024/11/23 15:22:27

一、概述

kotlin 2.0.0版本英文官方文档

The Kotlin 2.0.0 release is out and the new Kotlin K2 compiler is Stable! Additionally, here are some other highlights:
Kotlin 2.0.0发布了,新的Kotlin K2编译器已经稳定了。此外,以下是其他一些亮点:

  • New Compose compiler Gradle plugin
  • Generation of lambda functions using invokedynamic
  • The kotlinx-metadata-jvm library is now Stable
  • Monitoring GC performance in Kotlin/Native with signposts on Apple platforms
  • Resolving conflicts in Kotlin/Native with Objective-C methods
  • Support for named export in Kotlin/Wasm
  • Support for unsigned primitive types in functions with @JsExport in Kotlin/Wasm
  • Optimize production builds by default using Binaryen
  • New Gradle DSL for compiler options in multiplatform projects
  • Stable replacement of the enum class values generic function
  • Stable AutoCloseable interface

二、局部变量和进一步的作用域

以前,如果一个变量在if条件中被计算为非空,则该变量将被智能强制转换。关于这个变量的信息将在if块的范围内进一步共享。

但是,如果在if条件之外声明变量,则在if条件中无法获得有关该变量的信息,因此无法对其进行智能强制转换。这种行为在when表达式和while循环中也可以看到。

从Kotlin 2.0.0开始,如果在if、when或while条件中使用一个变量之前声明它,那么编译器收集的关于该变量的任何信息都可以在相应的块中进行智能转换。

当您想要将布尔条件提取到变量中时,这可能很有用。然后,您可以为变量指定一个有意义的名称,这将提高代码的可读性,并使以后在代码中重用该变量成为可能。例如:

三、使用逻辑或运算符进行类型检查

在Kotlin 2.0.0中,如果您将对象的类型检查与or操作符(||)结合起来,则会对其最接近的公共超类型进行智能强制转换。在此更改之前,总是对Any类型进行智能强制转换。

在这种情况下,您仍然必须手动检查对象类型,然后才能访问其任何属性或调用其函数。例如:

class Cat {
    //咕噜声
    fun purr() {
        print("cat Purr purr")
    }
}

fun petAnimal(animal: Any) {
    val isCat = animal is Cat
    if (isCat) {
        //在Kotlin 2.0.0中,编译器可以访问关于isCat的信息,
        // 所以它知道动物被智能铸造为Cat类型。因此,可以调用purr()函数。
        
        //在Kotlin 1.9.20中,编译器不知道
        //调用purr()函数触发错误。
        // animal.purr()

        // 2.0之前的版本,
        // (animal as Cat).purr()
    }
}

fun main() {
    val ketty = Cat()
    petAnimal(ketty)
}

四、使用逻辑或运算符进行类型检查

在Kotlin 2.0.0中,如果您将对象的类型检查与or操作符(||)结合起来,则会对其最接近的公共超类型进行智能强制转换。在此更改之前,总是对Any类型进行智能强制转换。

在这种情况下,您仍然必须手动检查对象类型,然后才能访问其任何属性或调用其函数。例如:

interface Status {
    fun signal() {}
}
interface Ok : Status
interface Postponed : Status
interface Declined : Status

fun signalCheck(signalStatus: Any) {
    if (signalStatus is Postponed || signalStatus is Declined) {
        // signalStatus is smart-cast to a common supertype Status;  signalStatus被智能转换为一个普通的超类型Status
//        signalStatus.signal()
        // Prior to Kotlin 2.0.0, signalStatus is smart cast; 在Kotlin 2.0.0之前,signalStatus是智能强制转换
        // to type Any, so calling the signal() function triggered an ; 输入Any,所以调用signal()函数会触发一个
        // Unresolved reference error. The signal() function can only; 未解析的引用错误。signal()函数只能
        // be called successfully after another type check: ; 在另一次类型检查后被成功调用:

        // check(signalStatus is Status)
        // signalStatus.signal()
    }
}

五、内联函数

在Kotlin 2.0.0中,K2编译器以不同的方式处理内联函数,允许它结合其他编译器分析来确定智能强制转换是否安全。

具体来说,内联函数现在被视为具有隐式的callsInPlace契约。这意味着任何传递给内联函数的lambda函数都会被就地调用。由于lambda函数是就地调用的,编译器知道lambda函数不会泄漏对其函数体中包含的任何变量的引用。

编译器使用这些知识和其他编译器分析来决定智能转换捕获的任何变量是否安全。例如:

interface Processor {
    fun process()
}

inline fun inlineAction(f: () -> Unit) = f()

fun nextProcessor(): Processor? = null

fun runProcessor(): Processor? {
    var processor: Processor? = null
    inlineAction {
        // In Kotlin 2.0.0, the compiler knows that processor
        // is a local variable, and inlineAction() is an inline function, so
        // references to processor can't be leaked. Therefore, it's safe
        // to smart-cast processor.

        // If processor isn't null, processor is smart-cast
        if (processor != null) {
            // The compiler knows that processor isn't null, so no safe call
            // is needed
            processor.process()

            // In Kotlin 1.9.20, you have to perform a safe call:
            // processor?.process()
        }

        processor = nextProcessor()
    }

    return processor
}

六、函数类型的属性

在Kotlin的早期版本中,有一个bug意味着带有函数类型的类属性不能智能强制转换。我们在Kotlin 2.0.0和K2编译器中修复了这个行为。例如:

class Holder(val provider: (() -> Unit)?) {
    fun process() {
        // In Kotlin 2.0.0, if provider isn't null, then
        // provider is smart-cast
        if (provider != null) {
            // The compiler knows that provider isn't null
            provider()

            // In 1.9.20, the compiler doesn't know that provider isn't
            // null, so it triggers an error:
            // Reference has a nullable type '(() -> Unit)?', use explicit '?.invoke()' to make a function-like call instead
        }
    }
}

如果重载调用操作符,也适用此更改。例如:

interface Provider {
    operator fun invoke()
}

interface Processor : () -> String

class Holder(val provider: Provider?, val processor: Processor?) {
    fun process() {
        if (provider != null) {
            provider()
            // In 1.9.20, the compiler triggers an error:
            // Reference has a nullable type 'Provider?' use explicit '?.invoke()' to make a function-like call instead
        }
    }
}

七、异常处理

在Kotlin 2.0.0中,我们对异常处理进行了改进,以便将智能强制转换信息传递给catch和finally块。此更改使代码更安全,因为编译器会跟踪对象是否具有可空类型。例如:

fun testString() {
    var stringInput: String? = null
    // stringInput is smart-cast to String type
    stringInput = ""
    try {
        // The compiler knows that stringInput isn't null
        println(stringInput.length)
        // 0

        // The compiler rejects previous smart cast information for
        // stringInput. Now stringInput has the String? type.
        stringInput = null

        // Trigger an exception
        if (2 > 1) throw Exception()
        stringInput = ""
    } catch (exception: Exception) {
        // In Kotlin 2.0.0, the compiler knows stringInput
        // can be null, so stringInput stays nullable.
        println(stringInput?.length)
        // null
        println("捕获到的异常信息:$exception")
        // In Kotlin 1.9.20, the compiler says that a safe call isn't
        // needed, but this is incorrect.
    }finally {
        println("执行了 finally 逻辑")
    }
}

运行结果
在这里插入图片描述

八、kt_200.kt文件代码

package com.example.test.ktversion

// https://kotlinlang.org/docs/whatsnew20.html
class Cat {
    //咕噜声
    fun purr() {
        print("cat Purr purr")
    }
}

fun petAnimal(animal: Any) {
    val isCat = animal is Cat
    if (isCat) {
        //在Kotlin 2.0.0中,编译器可以访问关于isCat的信息,
        // 所以它知道动物被智能铸造为Cat类型。因此,可以调用purr()函数。

        //在Kotlin 1.9.20中,编译器不知道
        //调用purr()函数触发错误。
        // animal.purr()

        // 2.0之前的版本,
        // (animal as Cat).purr()
    }
}

// Type checks with logical or operator  将对象的类型检查与or操作符(||)结合起来
interface Status {
    fun signal() {}
}
interface Ok : Status
interface Postponed : Status
interface Declined : Status

fun signalCheck(signalStatus: Any) {
    if (signalStatus is Postponed || signalStatus is Declined) {
        // signalStatus is smart-cast to a common supertype Status;  signalStatus被智能转换为一个普通的超类型Status
//        signalStatus.signal()
        // Prior to Kotlin 2.0.0, signalStatus is smart cast; 在Kotlin 2.0.0之前,signalStatus是智能强制转换
        // to type Any, so calling the signal() function triggered an ; 输入Any,所以调用signal()函数会触发一个
        // Unresolved reference error. The signal() function can only; 未解析的引用错误。signal()函数只能
        // be called successfully after another type check: ; 在另一次类型检查后被成功调用:

        // check(signalStatus is Status)
        // signalStatus.signal()
    }
}

// Inline functions
interface Processor {
    fun process()
}

inline fun inlineAction(f: () -> Unit) = f()

fun nextProcessor(): Processor? = null

fun runProcessor(): Processor? {
    var processor: Processor? = null
    inlineAction {
        // In Kotlin 2.0.0, the compiler knows that processor ;  在Kotlin 2.0.0中,编译器知道这个处理器
        // is a local variable, and inlineAction() is an inline function, so ; 是一个局部变量,而inlineAction()是一个内联函数,所以
        // references to processor can't be leaked. Therefore, it's safe ; 对处理器的引用不能泄露。因此,它是安全的
        // to smart-cast processor. ; 到智能转换处理器。

        // If processor isn't null, processor is smart-cast; 如果processor不为空,则processor是smart-cast
        if (processor != null) {

            // The compiler knows that processor isn't null, so no safe call; 编译器知道处理器不是null,所以没有安全调用
            // is needed ; 需要
//            processor.process()

            // In Kotlin 1.9.20, you have to perform a safe call:
            // processor?.process()
        }
        processor = nextProcessor()
    }

    return processor
}

// Properties with function types  函数类型的属性
class Holder(val provider: (() -> Unit)?) {
    fun process() {
        // In Kotlin 2.0.0, if provider isn't null, then
        // provider is smart-cast
        if (provider != null) {
            // The compiler knows that provider isn't null
//            provider()

            // In 1.9.20, the compiler doesn't know that provider isn't
            // null, so it triggers an error:
            // Reference has a nullable type '(() -> Unit)?', use explicit '?.invoke()' to make a function-like call instead
        }
    }
}

//This change also applies if you overload your invoke operator. For example:
interface Provider {
    operator fun invoke()
}
interface Processor2 : () -> String

class Holder2(val provider: Provider?, val processor: Processor2?) {
    fun process() {
        if (provider != null) {
//            provider()
            // In 1.9.20, the compiler triggers an error:
            // Reference has a nullable type 'Provider?' use explicit '?.invoke()' to make a function-like call instead
        }
    }
}

// 异常处理
fun testString() {
    var stringInput: String? = null
    // stringInput is smart-cast to String type
    stringInput = ""
    try {
        // The compiler knows that stringInput isn't null
        println(stringInput.length)
        // 0

        // The compiler rejects previous smart cast information for
        // stringInput. Now stringInput has the String? type.
        stringInput = null

        // Trigger an exception
        if (2 > 1) throw Exception()
        stringInput = ""
    } catch (exception: Exception) {
        // In Kotlin 2.0.0, the compiler knows stringInput
        // can be null, so stringInput stays nullable.
        println(stringInput?.length)
        // null
        println("捕获到的异常信息:$exception")
        // In Kotlin 1.9.20, the compiler says that a safe call isn't
        // needed, but this is incorrect.
    }finally {
        println("执行了 finally 逻辑")
    }
}
fun main() {
    val ketty = Cat()
    petAnimal(ketty)
    testString()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2182088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux操作系统中dubbo

1、简介 dubbo框架是做微服务通信的,是由阿里巴巴开发,后捐赠给阿帕奇基金会。 2、与OpenFeign的区别 dubbo是采用RPC协议实现微服务通信,OpenFeign是采用Http请求的方式实现的。 OpenFeign 最简单的,就是Spring公司开发的&am…

TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点

论文标题: 英文:TinyAP: An intelligent Access Point to combat Wi-Fi attacks using TinyML中文:TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点 作者信息: Anand Agrawal 和 Rajib Ranjan Maiti,来自印…

C语言常用标准库 -- 5.<time.h>

目录 引言 5. C标准库--time.h 5.1 简介 5.2 常量与宏 5.3 库变量 5.4 库宏 5.5 库函数 5.6 注意事项 🌈你好呀!我是 程序猿 🌌 2024感谢你的陪伴与支持 ~ 🚀 欢迎一起踏上探险之旅,挖掘无限可能,…

线程池面试集

目录 线程池中提交一个任务的流程是怎样的? 线程池有五种状态 如何优雅的停止一个线程? 线程池的核心线程数、最大线程数该如何设置? 如何理解Java并发中的可见性、原子性、有序性? Java死锁如何避免? 线程池中提交一个任务的流程是怎样的? 线程池有五种状态 如何优…

【docker学习】Linux系统离线方式安装docker环境方法

centos7-linux安装docker(离线方式) 下载docker的安装文件 https://download.docker.com/linux/static/stable/x86_64/ 下载的是:docker-18.06.3-ce.tgz 这个压缩文件 将docker-18.06.3-ce.tgz文件上传到centos7-linux系统上,用ftp工具上传即可 解压…

《RabbitMQ篇》基本概念介绍

MQ功能 解耦 MQ允许不同系统或组件之间松散耦合。发送者和接收者不需要直接连接,从而提高了系统的灵活性和可维护性。异步处理 使用MQ可以实现异步消息传递,发送者可以将消息放入队列后立即返回,不必等待接收者处理。这提高了系统的响应速度…

鸿蒙NEXT开发-ArkTS(基于最新api12稳定版)

注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

Spring IoC笔记

目录 1.什么是 IoC? 2.IoC类注解(五大注解) 2.1那为什么要这么多类注解? 2.2五大注解是不是可以混用? 2.3程序被spring管理的条件是? 3.bean对象 3.1Bean 命名约定 3.2获取bean对象 4.⽅法注解 B…

《应急通信产业发展研究报告》蓝皮书解读

近日,中国信通院发布了《应急通信产业发展研究报告》蓝皮书,该报告是对中国应急通信产业现状、发展趋势及其政策环境的综合分析,旨在为行业发展提供参考与指导。以下是小编对该蓝皮书的一些内容解读: 1.应急通信的重要性 应急通信…

2.点位管理|前后端如何交互——帝可得后台管理系统

目录 前言点位管理菜单模块1.需求说明2.库表设计3.生成基础代码0 .使用若依代码生成器最终目标1.创建点位管理2.添加数据字典3.配置代码生成信息4.下载代码并导入项目 4.优化菜单——点位管理1.优化区域管理2.增加点位数3. 合作商4.区域管理中添加查看详情功能5.合作商添加点位…

【拥抱AIGC】通义灵码扩展管理

通义灵码提供了扩展管理,支持自定义指令,满足企业编码场景的扩展诉求。 适用版本 企业标准版、企业专属版 通义灵码管理员、组织内全局管理员(专属版)在通义灵码控制台-扩展管理中,进行自定义指令的管理、查看自定义…

解锁数据宝藏:AI驱动搜索工具,让非结构化数据“说话

哈哈,说起这个 AI 搜索演示啊,那可真是个有意思的话题!非结构化数据,这家伙虽然难搞,但价值却是杠杠的。今天呢,咱就好好聊聊怎么借助 Fivetran 和 Milvus,快速搭建一个 AI 驱动的搜索工具,让企业能从那些乱七八糟的数据里淘到金子! 一、非结构化数据的挑战与机遇 首…

PCL 点云条件滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 条件定义与滤波 2.1.2 可视化函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接: PCL点云算法与项目实战案例汇总(长期更新&#…

Python从入门到高手4.1节-掌握条件控制语句

目录 4.1.1 理解条件控制 4.1.2 if, elif, else 4.1.3 条件表达式 4.1.4 条件控制可以嵌套 4.1.5 if语句的三元运算 4.1.6 国庆节快乐 4.1.1 理解条件控制 在日常生活中,我们常喜欢说如果, "如果怎么样,那么就会怎么样"。"如果&qu…

240930_CycleGAN循环生成对抗网络

240930_CycleGAN循环生成对抗网络 CycleGAN,也算是笔者记录GAN生成对抗网络的第四篇,前三篇可以跳转 240925-GAN生成对抗网络-CSDN博客 240929-DCGAN生成漫画头像-CSDN博客 240929-CGAN条件生成对抗网络-CSDN博客 在第三篇中,我们采用了p…

【Lazy ORM +Netty+DB开发一个内网渗透工具 wu-lazy-cloud-network(1.2.8-JDK17-SNAPSHOT)】

【Lazy ORM NettyDB开发一个内网渗透工具 wu-lazy-cloud-network(1.2.8-JDK17-SNAPSHO)】 环境 Java 17Spring Boot 3.xLazy ORMNettyMysql、H2 更新日志 版本1.2.8-JDK17-SNAPSHOT [change] 原《内网穿透》更改为服务端渗透客户端 [change] 新增服务…

Unity 代码裁剪(Strip Engine Code)

文章目录 0.IL2CPP 打包运行闪退问题1.什么是代码裁剪2.为什么要使用代码裁剪3.代码裁剪设置与级别4.强制保留代码4.1 使用[Preserve]标签4.2 使用Link.xml文件 5.Strip中遇到的问题及解决方法6.注意事项 0.IL2CPP 打包运行闪退问题 Google Play要求从2019年8月1日起apk必须支…

Spring系列 AOP实现过程

文章目录 实现原理EnableAspectJAutoProxyAnnotationAwareAspectJAutoProxyCreator 代理创建过程wrapIfNecessarygetAdvicesAndAdvisorsForBeanfindCandidateAdvisorsfindAdvisorsThatCanApply createProxy AspectJ注解处理代理调用过程 实现原理 本文源码基于spring-aop-5.3.…

Arweave的经济学模型

一、存储成本和挖矿奖励 1.1 永久数据存储的成本 由于 Arweave 的核心功能是为其用户提供永久存储,因此必须定义这种存储的定价机制。 作为计算永久存储一份数据的成本的前提,我们必须首先定义单个时间段的数据存储成本: 自数字数据存储技…

算法-数组笔记

二分搜索 . - 力扣(LeetCode) 使用场景 前提是数组为有序数组,同时题目还强调数组中无重复元素。 因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大…