为什么这个不能编译?

fun <T> returnOptionalOf(t: T): Optional<T> {
    val optional: Optional<T> = Optional.of(t)
    return optional
}

错误是

类型不匹配:推断的类型为T,但应为T&amp;Any

如何让它工作?

这样编译就好了:

fun returnOptionalOfString(t: String): Optional<String> {
    val optional: Optional<String> = Optional.of(t)
    return optional
}

推荐答案

我的第一个建议是,尽量避免使用Optional种考特林语言.可为空的类型提供了相同的编译时保证,即一个值是否可以容纳空值,它们迫使您在正确的位置判断是否为空,而且它们更加惯用(还有大量的语法糖分可以帮助处理可为空的值,如?:?.操作符).

现在回到你的具体问题上,你看到的是几个因素对你不利的组合:

  • 在函数签名中,根本没有约束T.这意味着T可以是一个可空的类型(例如,String?),这反过来又意味着这个函数接受空值.注意,Optional.of是一个Java函数,它期望一个非空值,如果给出null作为参数,则抛出NPE.在这种情况下,您可能需要仔细判断抛出NPE是否是您想要的函数.

  • 另一个(更大的)问题是,您可能会假设Optional<T>T中是协变的,但它实际上是不变的(可能是因为它是一个Java类,没有对它做任何特殊的处理,但确实有an issue to change this个).更清楚地说,这意味着即使AB的子类型,Optional<A>也不是Optional<B>的子类型,因此不能将Optional<String>值赋给类型为Optional<String?>的变量.

  • 第三件事是,像ofofNullable这样的Optional个工厂函数实际上返回您传递的类型的不可为空的投影,因此总是Optional<T & Any>(因为空值将分别失败或导致空的Optional).例如,Optional.of<String?>("abc")仍然返回Optional<String>,这与OptionalT中是不变的事实不符.

这解释了为什么您的optional变量的显式类型(Optional<T>)是不正确的.因为Optional.of返回Optional<T & Any>,不能将其赋给Optional<T>类型的变量(即使T & AnyT的子类型).

这可能有很多行话,所以让我使用您的字符串示例来澄清一下,但是我们不使用String作为T,而是使用String?:

fun returnOptionalOfString(t: String?): Optional<String?> {
    val optional: Optional<String?> = Optional.of(t) // error here
    return optional
}

在这里,您将看到赋值的相同错误,但用更简单的术语.

正如@marstran已经提到的,解决所有这些问题的一种方法是在处理Optional时只使用不可为空的类型.在您的例子中,这意味着使用: Any约束T:

fun <T : Any> returnOptionalOf(t: T): Optional<T> {
    val optional: Optional<T> = Optional.of(t)
    return optional
}

Kotlin相关问答推荐

如何在Kotlin中为两个数据类创建可重用的方法?

将基于注册的服务转换为流

在Jetpack Compose中创建波浪式文本动画:顺序中断问题

处理合成层次 struct 中的深层按钮以切换视图

如何在Android应用判断上运行多个查询

使函数同时挂起和取消挂起

Kotlin 获取继承类的默认 hashCode 实现

jlink:在合并模块和 kotlin.stdlib 中打包 kotlin.*

是什么让 Kotlin 中的 String 类能够使用方括号?

关于 Kotlin 函数类型转换的问题

Kotlin:不允许在辅助构造函数参数上使用val

在 Kotlin 中,当枚举类实现接口时,如何解决继承的声明冲突?

将 Gradle 子元素与 Kotlin 多平台一起使用

在 Kotlin 中通过反射获取 Enum 值

在 Spring Framework 5.1 中注册具有相同名称的测试 bean

Kotlin 顶级函数与对象函数

如何解决此错误请Kotlin:[Internal Error] java.lang.ExceptionInInitializerError

在调用Kotlin数据类中的超类构造函数之前访问函数

使用导航组件在不同的图形之间导航

Failure delivering result on activity result