5.7.7 未使用的返回值检查器
4 分钟阅读
原文链接: https://kotlinlang.org/docs/unused-return-value-checker.html
5.7.7 未使用的返回值检查器
实验性-通用
注意: 此特性计划在未来的 Kotlin 版本中稳定并改进。欢迎你在我们的问题跟踪器 YouTrack 中提供反馈。更多信息请参阅相关的 KEEP 提案。
未使用的返回值检查器可以检测被忽略的结果。这些是从表达式返回、产生了 Unit、Nothing 或 Nothing? 之外的值,并且没有被:
- 存入变量或属性。
- 返回或抛出。
- 作为实参传给其他函数。
- 用作调用或安全调用中的接收者。
- 在
if、when、while等条件中检查。 - 用作 lambda 的最后一条语句。
该检查器不会对 ++ 和 -- 这类自增运算报告被忽略的结果,也不会对右侧会退出当前函数的布尔短路(例如 condition || return)报告。
你可以用未使用的返回值检查器来发现这样的缺陷:函数调用产生了有意义的结果,但结果被默默丢弃了。这有助于避免意外行为,也让这类问题更容易排查。
下面的例子创建了一个字符串却从未使用,因此检查器会把它报告为被忽略的结果:
| |
配置未使用的返回值检查器
你可以用 -Xreturn-value-checker 编译器选项控制编译器如何报告被忽略的结果。
它有下面几种模式:
注意: 所有被标记的函数都会按此传播,因此在使用你的代码作为依赖的项目中,只要启用了检查器,被忽略的结果就会被报告。
要在你的项目中使用未使用的返回值检查器,请把该编译器选项添加到构建配置文件中:
Gradle
| |
Maven
| |
标记函数以检查被忽略的结果
当你把 -Xreturn-value-checker 编译器选项设置为 check 时,检查器只会报告来自已标记表达式的被忽略结果,就像 Kotlin 标准库中的大多数函数那样。
要标记你自己的代码,请使用 @MustUseReturnValues 注解。你可以按希望检查器覆盖的范围,把它应用于文件、类或函数。
例如,你可以标记整个文件:
| |
或者标记某个特定的类:
| |
注意: 你可以把
-Xreturn-value-checker编译器选项设置为full,从而对整个项目应用该检查器。使用这个选项时,你不必用@MustUseReturnValues标注代码。
抑制对忽略结果的报告
你可以用 @IgnorableReturnValue 注解来抑制对特定函数的报告。对于那些忽略结果很常见也很正常的函数(例如 MutableList.add),可以加上该注解:
| |
你也可以不注解函数本身而抑制警告。做法是用下划线语法(_)把结果赋给一个特殊的匿名变量:
| |
函数重写中的被忽略结果
当你重写一个函数时,重写会继承基类声明上注解所定义的报告规则。当基类声明属于 Kotlin 标准库或其他库依赖时也是如此,因此检查器会对 Any.hashCode() 这类函数的重写报告被忽略的结果。
此外,你不能用另一个要求必须使用其返回值的函数来重写被 @IgnorableReturnValue 标记的函数。不过,在带 @MustUseReturnValues 注解的类或接口中,如果某个重写的结果可以安全忽略,你可以用 @IgnorableReturnValue 标记它:
| |
检查高阶函数中未使用的结果
有些高阶函数(例如 let 作用域函数)会返回 lambda 的结果。要检查高阶函数中未使用的 lambda 结果,请在函数的契约中添加实验性的 returnsResultOf() 契约。
警告: Kotlin 契约是实验性的。要启用它,请在声明带契约的函数时加上
@OptIn(ExperimentalContracts::class)注解。
下面是一个例子:
| |
然后你就可以使用带这种契约的函数(例如 .customLet())来检查 lambda 的结果是否被使用:
| |
警告:
returnsResultOf()契约需要一个单独的编译器选项才能启用。请注意,使用它会产生预发布版本的二进制文件,Kotlin 2.4.0 之前的编译器版本无法读取。
要为你的项目启用它,请在构建文件中添加以下编译器选项:
Gradle
| |
Maven
| |
与 Java 注解的互操作
有些 Java 库使用类似的机制,但注解不同。未使用的返回值检查器会把以下注解视为等同于使用 @MustUseReturnValues:
com.google.errorprone.annotations.CheckReturnValueedu.umd.cs.findbugs.annotations.CheckReturnValueorg.jetbrains.annotations.CheckReturnValueorg.springframework.lang.CheckReturnValueorg.jooq.CheckReturnValue
它还会把 com.google.errorprone.annotations.CanIgnoreReturnValue 视为等同于使用 @IgnorableReturnValue。