将 kotlin 与项目反应堆一起使用时的平台类型和 jsr-305 注释
Platform types and jsr-305 annotations when using kotlin with project reactor
我正在使用带有 kotlin 的项目反应器。正如预期的那样,由于我正在编写调用 java 代码的 kotlin 代码,所以来自项目反应堆操作员的所有类型签名都显示为平台类型。例如
//here i is inferred as Int!
Mono.just(1).map { i -> i + 1 }
通读项目反应器的文档,似乎有一种方法可以断言所有类型都不可为空,并将这些类型推断为不可为空的类型。 https://projectreactor.io/docs/core/release/reference/#kotlin-null-safety
Kotlin support for JSR 305 annotations and Reactor nullability annotations provide null-safety for the whole Reactor API to Kotlin developers, with the advantage of dealing with null-related issues at compile time.
我曾尝试使用建议的编译器选项,但没有成功。使用以下 kotlin 配置,i
的类型仍然显示为 Int!
,而我现在希望它是 Int
.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.6.10"
application
}
group = "me.stef"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
implementation("io.projectreactor:reactor-core:3.4.14")
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = listOf("-Xjsr305=strict")
}
}
application {
mainClass.set("MainKt")
}
我正在使用带有 kotlin 插件版本 213-1.6.10-release-961-IJ6777.52
的 intelliJ IDEA Ultimate 版本 2021.3.2
我知道我可以使用显式类型注释将平台类型转换为可空或非空类型,但我希望尽可能避免这种情况。
所以我的问题是:
- 我是否正确地解释了文档以理解在将项目反应堆与 kotlin 一起使用时确实有一种方法可以强制执行不可为空的类型?
- 如果我理解正确,并且
jsr305
编译器选项是实现我的目标的方式,那么我做错了什么?
- 如果那不是实现我目标的方法,我该怎么做?
- 会不会是intellij的问题?
实际上该行为是设计使然,因为 @NonNullApi
which is applied to a package from where you are calling the method (map
) 没有使用默认限定符的类型,只有 METHOD
和 PARAMETER
。特别是,这意味着 Kotlin 编译器不会增强类型参数位置内的类型,而只会增强 return 类型和值参数位置中的整个类型。
可以用下面的代码证明:
fun main() {
// useless unsafe call before `get()` is reported because
// the Kotlin compiler already enhanced the return type of `blockOptional` to not-null
Mono.just(1).blockOptional()?.get()
}
在您的特定情况下,lambda 的值参数 i
映射到 map
声明中 Function
的 T
类型参数,对应于 输入 use 位置。这就是 Kotlin 编译器不增强这种类型的原因。
请注意,Kotlin 编译器在类型使用位置默认情况下支持从 Java 增强类型。请参阅 following 编译器测试。
因此,为 reactor 创建一个功能请求以扩展其 NonNullApi
注释的范围以键入使用位置可能是有意义的。
我正在使用带有 kotlin 的项目反应器。正如预期的那样,由于我正在编写调用 java 代码的 kotlin 代码,所以来自项目反应堆操作员的所有类型签名都显示为平台类型。例如
//here i is inferred as Int!
Mono.just(1).map { i -> i + 1 }
通读项目反应器的文档,似乎有一种方法可以断言所有类型都不可为空,并将这些类型推断为不可为空的类型。 https://projectreactor.io/docs/core/release/reference/#kotlin-null-safety
Kotlin support for JSR 305 annotations and Reactor nullability annotations provide null-safety for the whole Reactor API to Kotlin developers, with the advantage of dealing with null-related issues at compile time.
我曾尝试使用建议的编译器选项,但没有成功。使用以下 kotlin 配置,i
的类型仍然显示为 Int!
,而我现在希望它是 Int
.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.6.10"
application
}
group = "me.stef"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
implementation("io.projectreactor:reactor-core:3.4.14")
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = listOf("-Xjsr305=strict")
}
}
application {
mainClass.set("MainKt")
}
我正在使用带有 kotlin 插件版本 213-1.6.10-release-961-IJ6777.52
2021.3.2
我知道我可以使用显式类型注释将平台类型转换为可空或非空类型,但我希望尽可能避免这种情况。
所以我的问题是:
- 我是否正确地解释了文档以理解在将项目反应堆与 kotlin 一起使用时确实有一种方法可以强制执行不可为空的类型?
- 如果我理解正确,并且
jsr305
编译器选项是实现我的目标的方式,那么我做错了什么? - 如果那不是实现我目标的方法,我该怎么做?
- 会不会是intellij的问题?
实际上该行为是设计使然,因为 @NonNullApi
which is applied to a package from where you are calling the method (map
) 没有使用默认限定符的类型,只有 METHOD
和 PARAMETER
。特别是,这意味着 Kotlin 编译器不会增强类型参数位置内的类型,而只会增强 return 类型和值参数位置中的整个类型。
可以用下面的代码证明:
fun main() {
// useless unsafe call before `get()` is reported because
// the Kotlin compiler already enhanced the return type of `blockOptional` to not-null
Mono.just(1).blockOptional()?.get()
}
在您的特定情况下,lambda 的值参数 i
映射到 map
声明中 Function
的 T
类型参数,对应于 输入 use 位置。这就是 Kotlin 编译器不增强这种类型的原因。
请注意,Kotlin 编译器在类型使用位置默认情况下支持从 Java 增强类型。请参阅 following 编译器测试。
因此,为 reactor 创建一个功能请求以扩展其 NonNullApi
注释的范围以键入使用位置可能是有意义的。