Kotlin
A concise multiplatform language developed by JetBrains
Kotlin 1.5.0-RC 版本发布:标准库和测试库的变更
Kotlin 1.5.0-RC 版本已具备 1.5.0 版本计划的所有特性——请查看即将发布版本的全部内容! 新的语言特性,标准库的更新,改进的测试库以及许多正在逐步完善的改动。 在正式版发行之前仅有的改动将是问题修复。
在您的项目中尝试 1.5.0-RC 的现代化 Kotlin API,并帮助我们改善发行版吧! 您可以向我们的问题跟踪器(YouTrack)报告所遇到的任何问题。
在这篇文章中,我们将向您介绍 1.5.0-RC 中 Kotlin 标准库和测试库的变更:
您可以在下面找到所有详细信息!
稳定的无符号整型
标准库中包含了无符号整型 API,可用于处理非负整数运算。包括:
- 无符号的数字类型:
UInt
,ULong
,UByte
,UShort
,以及相关函数,例如转换。 - 集合类型:无符号整型的数组,范围和级数:
UIntArray
,UIntRange
,以及其他类型的类似容器。
无符号整型从 Kotlin 1.3 可以使用。 现在,我们将无符号整型和对他们的操作分类为稳定类型,使它们无需声明 opt-in 即可使用,并且可以在实际项目中安全使用。
新的稳定 API 是:
- 稳定的无符号整型
- 无符号整型的范围和级数
- 使用无符号整型进行运算的函数
无符号整型数组仍保留在 Beta 中。 由数组支持的无符号整数 varargs 也是如此。 如果要在代码中使用它们,可以使用 @ExperimentalUnsignedTypes
注解选择加入。
了解更多有关 Kotlin 无符号整型的信息。
Java.nio.file.Path API 的扩展
Kotlin 现在提供了一种通过 non-blocking Java IO 扩展函数以Kotlin 惯用风格调用现代的无阻塞 Java IO
的方法。
这是一个小示例:
这些扩展是在 Kotlin 1.4.20 中作为实验功能引入的,现在无需 opt-in 注解即可使用。 查看 kotlin.io.path
软件包,以获取可以使用的函数列表。
File API 的现有扩展仍然可用,因此你可以自由选择喜欢的API。
与语言环境无关的大写和小写的 API
许多人都熟悉更改字符串和字符大小写的标准库函数: toUpperCase()
, toLowerCase()
, toTitleCase()
。 通常它们可以正常工作,但是在处理不同的平台语言环境设置时会让你头痛–它们都对语言环境设置敏感,这意味着它们的结果可能会因语言环境设置而异。 例如,"Kotlin".toUpperCase()
返回什么? 你会说:“显然是KOTLIN
”。 但是如果你把语言环境设置为土耳其,大写字母i
是İ
,因此结果会有所不同:KOTLİN
。
现在有一个新的与语言环境无关的 API,用于更改字符串和字符的大小写: uppercase()
, lowercase()
, titlecase()
扩展及其对应的 * Char()
。 您可能已经在 1.4.30 预览中尝试过了。
无论平台的区域设置如何,新函数的返回结果是相同的。 只需调用这些函数,其余的留给标准库。
无论平台的区域设置如何,新函数的返回结果是相同的。
只需调用这些函数,其余的留给标准库。
在 JVM 上,可以通过使用当前语言环境作为参数调用新函数来执行对语言环境敏感的大小写更改:
新函数将完全取代已经废弃的旧函数。
清除字符到编码值和字符到数字值的转换
获取字符的 UTF-16 编码的操作-toInt()
函数-是一个常见的陷阱,因为它看起来非常类似于只有一个数字的字符串的 String.toInt()
操作,该操作产生一个由该字符串表示的 Int
。
此外,没有通用函数会为Char '4'
返回数字值 4
。
为了解决这些问题,现在提供了一组新函数,用于在字符及数字码和数字值之间进行转换:
Char(code)
和Char.code
在 char 及其数字码之间转换。Char.digitToInt(radix: Int)
和 its*OrNull
从指定基数的字符创建一个整数。Int.digitToChar(radix: Int)
从一个数字创建一个字符,该数字表示指定基数中的整数。
这些函数具有清晰的名称,并使代码更具可读性:
从 Kotlin 1.4.30 开始预览模式下可用的新函数现已稳定。 字符到数字转换的旧函数( Char.toInt()
和其他数字类型的相似函数)和数字到字符转换(Long.toChar()
和类似的字符,但Int.toChar()
除外)的旧函数现在已经废弃。
Char API的多平台扩展方法
我们将继续扩展标准库的跨平台部分,以将其所有功能提供给跨平台项目的通用代码。
现在我们已经向全平台以及通用代码提供大部分的 Char
函数了。 这些函数包括:
- 检查一个字符是字母还是数字的
Char.isDigit()
,Char.isLetter()
,Char.isLetterOrDigit()
。 - 检查字符大小写的
Char.isLowerCase()
,Char.isUpperCase()
,Char.isTitleCase()
。 - 检查字符是否含有
Cn
(未定义)以外 Unicode 通用类别的Char.isDefined()
。 - 检查字符是否为 ISO 控制字符的
Char.isISOControl()
,其字节编码范围为\u0000
..\u001F
or\u007F
..\u009F
。
Char.category
属性及其返回的枚举类型CharCategory
(根据Unicode指示字符的通用类型)现可在跨平台项目访问。
精确版本的 String?.toBoolean()
Kotlin的String?.toBoolean()
函数广泛用于通过字符串创建布尔值。 它的工作原理非常简单: 不论大小写,在"true"字符串上都为true
,而其他字所有符串(包括null
)上都为false
。
虽然这种表现看起来很自然,但它隐藏了潜在的异常情况。 通过该函数的转换,无论字符串具有哪些非常规的值,你都将得到一个布尔值。
String?.toBoolean() 新的区分大小写的严格版本有助于避免此类错误:
String.toBooleanStrict()
会对除“true”和“false”以外的所有输入抛出异常。String.toBooleanStrictOrNull()
会对除“true”和“false”以外的所有输入都返回null
。
Duration API 的更改
从1.3.50版开始的实验性持续时间和时间测量API 已在stdlib中提供。 提供了用于精确测量时间间隔的API。
这些API的其中一个关键类是 Duration
。 它表示两个时刻之间的时间长度。 在1.5.0,Duration其API和内部形式发生了重大变化。
Duration
其内部现在使用Long
值类型代替了Double
。 Long
值的表示范围相当于纳秒级的一百多年或毫秒级的一亿年。 但是,此前的亚纳秒级持续时间已不再支持。
我们还引入了新的属性值,用于获取duration
的Long
值。 它们可用于各种时间单位:Duration.inWholeMinutes
,Duration.inWholeSeconds
等。 这些函数用来替换基于Double
的属性,例如Duration.inMinutes
。
另一个改动是一组新的工厂函数,用于通过整数创建Duration
实例。 它们直接定义在Duration
类型中,以替换数字类型的旧扩展属性,例如Int.seconds
。
由于这些重大更改,所有持续时间和时间测量的API在1.5.0中仍处于试验阶段,需要@ExperimentalTime
注释来选择性引入。
请尝试新的版本,并在我们的问题跟踪器 YouTrack 中分享你的反馈。
数学运算: 向下取整和求余运算符
在Kotlin中,整数的除法运算符 (/
) 表示截断除法,它去掉了结果的小数部分。 在模运算中,还有另一种选择向下取整除法,其结果将向下取整 (朝较小的整数方向) ,从而对负数会产生不同的结果。
在之前,向下取整除法将要求传递一个自定义函数,如:
在1.5.0-RC,我们引入了codefloorDiv()
函数,该函数将对整数进行向下取整运算。floorDiv()
函数,该函数将对整数进行向下取整运算。
在1.5.0,我们引入了新的mod()
函数。 现在,它的功能完全符合其名称–-它返回模数,即向下取整除法的余数部分。
它不同于Kotlin的rem()
(或%
运算符) 。 模数是a
和a.floorDiv(b)* b
的差。 非零模数始终与b
具有相同的符号,而a%b
可以有不同的符号。 例如,在实现循环列表时,这可能会很有用:
集合: firstNotNullOf() and firstNotNullOfOrNull()
Kotlin集合API通过内置函数覆盖了一系列针对集合的流行操作。 对于不常见的案例,通常将这些函数调用结合到一起。 尽管它能完成任务,但通常来说看起来并不优雅,而且可能会导致额外的开销。
例如,要通过选择器函数获取集合的第一个非空结果,可以调用mapNotNull()
和first()
。 在1.5.0,通过新函数firstNotNullOf()
,你只需要一次调用便能做到。 我们与firstNotNullOf()
一同添加了它对应的*orNull()
函数,如果没有返回值,将返null。
以下是代码简洁后的示例。
假设你的类有一个可空属性,同时你需要获取类实例数组中的第一个非空值。
你可以通过迭代集合并检查属性是否为非null来实现:
另一种方式是使用旧函数mapNotNull()
和firstOrNull()
。 请注意, mapNotNull()
会创建一个中间集合,尤其是对于大型集合,这会消耗额外的内存。 因此,这里可能需要转换为序列。
这就是新函数看起来的样子:
测试库的变更
我们已有几个正式版没有发布 Kotlin 测试库 kotlin-test
的重要更新了,而现在我们提供了一些期待已久的改动。 在1.5.0-RC,你可以尝试许多新特性:
- 在多平台项目里只需要对
codekotlin-test
do单次依赖。>kotlin-test`单次依赖。 - 自动为Kotlin/JVM源集选择测试框架。
- 断言函数的更新。
多平台项目中的kotlin-test依赖
我们仍持续多平台项目配置流程的开发。 在1.5.0,我们让所有源集更加易于创建对kotlin-test
的依赖。
现在,你仅仅需要在通用测试源集中添加kotlin-test
依赖项。 Gradle插件将为其他源集推断出平台对应的依赖:
- 对于JVM源集则是
kotlin-test-junit
。 你可以显式指定切换到kotlin-test-junit-5
或kotlin-test-testng
(继续阅读了解具体方法)。 - 对于 Kotlin/JS 源集则是
kotlin-test-js
。 - 对于通用源集则是
kotlin-test-common
和kotlin-test-annotations-common
。 - Kotlin/Native源集没有多余的工件,因为Kotlin/Native提供了
kotlin-testAPI的内置实现。
为Kotlin/JVM源集自动选择测试框架
如上所述,一旦在通用测试源集中指定了kotlin-test
的依赖, JVM 源集就会自动创建对JUnit 4
的依赖。
在Groovy DSL上看起来是这样的:
而在Kotlin DSL则是如此:
你还可以在测试任务中简单地通过一个函数来切换到JUnit 5或TestNG:useJUnitPlatform()
或 useTestNG()
。
当你在仅面向JVM的项目中添加kotlin-test
依赖时也是如此。
断言函数的更新
在1.5.0,我们准备了许多新的断言函数,以及对现有断言函数的改进。
首先,我们来快速浏览下新的函数:
- 用于检查时速局类型的
assertIs<T>()
和assertIsNot<T>()
。 - 用于比较数组、序列以及所有
Iterable
内容的assertContentEquals()
。 更准确地说,它检查预期和实际的元素及其顺序是否一致。 Double
和Float
的assertEquals()
和assertNotEquals()
有新的重载,并带有第三个参数–精度。- 检查数组、列表、范围等是否
contains()
指定object
的assertContains()
。
以下是一个简短的示例,展示了这些函数的用法:
对于现有的断言函数——现在可以在assertTrue()
,assertFalse()
的lambda
参数内调用 suspending functions 了,以及expect(),因为这些函数现在是 内联 的。
尝试 Kotlin 1.5.0的所有特性
让 1.5.0-RC 为您的项目引入现代化的 Kotlin API!
在 IntelliJ IDEA 或 Android Studio 安装 1.5.0-RC 的 Kotlin 插件。 了解如何获取插件的EAP版本。
通过 1.5.0-RC 构建现有项目,以检查在 1.5.0 下它们如何工作。 由于预览版本更简易的配置,如有必要,你只需要将Kotlin版本更改为 1.5.0-RC
并调整依赖版本。
一如往常,你可以在 Kotlin Playground 在线尝试最新的版本。
Compatibility
与所有主要版本一样,某些先前宣布的变更的弃用周期将在 Kotlin 1.5.0 版本结束。
所有这些情况都经过了语言委员会的仔细审查,并在 Kotlin 1.5 兼容性指南中列出。
您也可以在 YouTrack 上浏览这些变更。
候选版本说明
Kotlin 1.5 最终候选版本现已推出,是时候开始编译和发布了! 与以前的里程碑版本不同,使用 Kotlin 1.5-RC 创建的二进制文件与 Kotlin 1.5.0 的兼容性可得到充分保证。
分享反馈
这是你能参与影响下一功能版本的最后机会了! 你可以向我们的问题跟踪器(YouTrack)报告所遇到的任何问题。 让Kotlin 1.5.0为了你和社区变得更好!