Edit Page

类型的检查与转换

is!is运算符

我们可以使用is 或者它的否定!is运算符检查一个对象在运行中是否符合所给出的类型:

if (obj is String) {
  print(obj.length)
}

if (obj !is String) { // same as !(obj is String)
  print("Not a String")
}
else {
  print(obj.length)
}

智能转换

在很多情况下,在Kotlin有时不用使用明确的转换运算符,因为编译器会在需要的时候自动为了不变的值和输入(安全)而使用is进行监测:

fun demo(x: Any) {
  if (x is String) {
    print(x.length) // x is automatically cast to String
  }
}

如果错误的检查导致返回,编译器会清楚地转换为一个正确的:

  if (x !is String) return
  print(x.length) // x is automatically cast to String

或者在右边是&&||

  // x is automatically cast to string on the right-hand side of `||`
  if (x !is String || x.length == 0) return

  // x is automatically cast to string on the right-hand side of `&&`
  if (x is String && x.length > 0)
      print(x.length) // x is automatically cast to String

这些智能转换在 when-expressionswhile-loops 也一样:

when (x) {
  is Int -> print(x + 1)
  is String -> print(x.length + 1)
  is IntArray -> print(x.sum())
}

Note that smart casts do not work when the compiler cannot guarantee that the variable cannot change between the check and the usage. More specifically, smart casts are applicable according to the following rules:

  • val local variables - always;
  • val properties - if the property is private or internal or the check is performed in the same module where the property is declared. Smart casts aren’t applicable to open properties or properties that have custom getters;
  • var local variables - if the variable is not modified between the check and the usage and is not captured in a lambda that modifies it;
  • var properties - never (because the variable can be modified at any time by other code).

“不安全”的转换运算符

通常,如果转换是不可能的,转换运算符会抛出一个异常。于是,我们称之为不安全的。在Kotlin这种不安全的转换会出现在插入运算符as (see operator precedence):

val x: String = y as String

记住null不能被转换为不可为空的String。例如,如果y是空,则这段代码会抛出异常。为了匹配Jave的转换语义,我们不得不在右边拥有可空的类型,就像:

val x: String? = y as String?

“安全的”(可为空的)转换运算符

为了避免异常的抛出,一个可以使用安全的转换运算符——as? ,它可以在失败时返回一个null

val x: String? = y as? String

记住尽管事实是右边的as?可使一个不为空的String类型的转换结果为可空的。