【问题标题】:Are nullable operators valid within generic class?可空运算符在泛型类中有效吗?
【发布时间】:2015-03-31 00:58:05
【问题描述】:

Kotlin 具有处理可空类型的漂亮特性(?.!!.)。但是这个只是打动我——如果你不知道你是在处理可空类型还是不可空类型怎么办?如果你有泛型类MyClass<T>,那么你只有一些类型T,就是这样。

Kotlin 是否允许将“可为空”运算符应用于泛型类型(此处为T),是否可以将类型设为可空类中(如T?),如果类将被实例化为可为空的类型——比如MyClass<String?>。是否会导致 MyClass 类型内的可空类型(如 C++ 中的指针——**std::string)类型为空?

【问题讨论】:

  • just type T 被解释为 T: Any? 所以没有“just type T”,因为编译器会认为它可以为空。您可以使用T: Any 定义一个不可为空的不同上限。

标签: generics nullable kotlin


【解决方案1】:

我刚刚在Web Demo试了一下。

class MyClass<T>(val x: T) {
  fun foo() {
    println(x.toString())
  }

  fun fooSave() {
    println(x?.toString())
  }

}

fun main(args: Array<String>) {
  MyClass<String?>(null).fooSave()
  MyClass<String?>(null).foo()
}

您似乎总是可以应用 null 安全运算符 ?.,即使该类型不一定可以为 null。

另一方面,您可以将泛型类型参数T 绑定到一个可为空的类型,在我的例子中为String?如果您传递null,实际上会产生NullPointerException .

编辑:自从提出问题以来,没有上限的泛型类型的语义已经改变。 T 现在解释为 T : Any?。但是上面的代码不再崩溃。原因是调用x.toString()会调用扩展函数Any?.toString()正确处理nulls。

如果我们把代码改成如下

class MyClass<T : Any>(val x: T) {
  fun foo() {
    println(x.toString())
  }

  fun fooSave() {
    println(x?.toString())
  }

}

fun main(args: Array<String>) {
  MyClass<String?>(null).fooSave()
  MyClass<String?>(null).foo()
}

它现在甚至不能编译,因为我们不能用String? 实例化T : Any。呼叫x?.toString() 也被标记为警告,表明安全呼叫是不必要的。

【讨论】:

  • 哇,如果可以的话,我会为该链接添加更多积分 :-) 非常感谢。更重要的是——您刚刚发现明确反对 null 并不能真正起作用。如果没有泛型,您将不得不编写 !!.toString(),但使用泛型编译器不知道 T 是什么并允许隐式检查。
  • 第二次检查,这个例子是特殊情况,因为toString是在root类型中定义的。这就是为什么(可能)它首先编译的原因——像length 这样的任何其他方法都需要向泛型添加约束,这意味着你必须提前决定你编写泛型类的类型——是否可以为空.
  • 你是对的。如果我将 T 设置为扩展任何类型,我根本无法将它绑定到可为空的类型,因为 T?不扩展 T。这是一个无法编译的示例:kotlin-demo.jetbrains.com/…
  • just type T 被解释为 T: Any? 所以没有“just type T”,因为编译器会认为它可以为空。您可以使用T: Any 定义一个不可为空的不同上限。
猜你喜欢
  • 2016-06-10
  • 1970-01-01
  • 2012-09-24
  • 2010-10-16
  • 2018-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多