在 Kotlin 中,“::class.simpleName”是做什么的?

In Kotlin, what does "::class.simpleName" do?

提问人:Kun.tito 提问时间:3/9/2022 更新时间:3/9/2022 访问量:751

问:

val var1: Any = "Carmelo Anthony"

我的印象是,当我执行以下操作时,会返回对象
的变量类型:
::class.simpleName

val var1Type = var1::class.simpleName
print(var1Type)

我得到和不StringAny

但是当我这样做时

val var2: String = var1

我得到一个Type mismatch: inferred type is Any but String was expected

Kotlin 变量赋值 推理赋值 运算符 类型不匹配

评论

0赞 Dai 3/9/2022
你的静态类型是 ,这就是原因。var1Any
0赞 Tobse 3/9/2022
可以通过从 Any 到 String 的类型转换来修复:val var2: String = var1 as String

答:

6赞 Dai 3/9/2022 #1
  • 在 Kotlin 中,运算符以 2 种形式存在:::class
  • 在您的例子中,运行时类型为 ,但静态类型为 。var1StringAny
    • 所以返回 for ,而不是 。var1::classKClassStringAny
  • 但是 Kotlin 的类型系统,就像大多数静态类型语言一样,不允许隐式缩小转换(即,给定一个类型为 的变量,你不能从另一个变量 () 静态类型为 ,因为可能有一个与 完全不兼容的运行时类型,例如一个对象。var2Stringvar2var3Anyvar3StringInputStream
    • ...即使可以证明(通过手动操作程序),-typed 值将始终是 .AnyString
    • 然而,幸运的是,Kotlin 的类型检查器是现代的,它的“智能转换”功能在使用运算符时遵循类型缩小的范围,这很简洁(TypeScript 也有,我认为任何其他语言都没有)。is
      • 如果您无法使用智能投射,或者可以通过其他方式向自己证明投射是安全的,请使用操作员执行不安全的投射。这样:。asvar2: String = var1 as String
        • (有点令人困惑的是,其他语言用作安全转换的运算符,啊)。as

在上下文中

fun main() {

    val var1: Any = "Carmelo Anthony"
    val var1Type = var1::class.simpleName
    println("var1's type: " + var1Type) // <-- This will print the *runtime type* of `var1` (String), not its static type (which is `Any`, *not* `String`).

    /*
    val var2: String = var1 // <-- Fails beause `var1` is `Any`, and `Any` is "wider" than `String`, and narrowing conversions always considered unsafe in languages like Kotlin, Java, etc.
    */
    val var2Unsafe: String  = var1 as  String; // <-- Doing this is unsafe because it will throw if `var1` is not a String.
    val var2Safe  : String? = var1 as? String; // <-- Doing this is safe because it `var2Safe` will be null if `var1` is not a String.
    
    println(var2Unsafe)
    println(var2Safe)
}

如果您熟悉其他语言,那么这里有一个不完整的等效操作及其语法表:

科特林 爪哇岛 JavaScript的 C# C++
获取静态类型 TypeName::class TypeName.class ConstructorName typeof(TypeName) typeid(TypeName)
获取运行时类型 variableName::class variableName.getClass() typeof variableName(内部函数) (对象)variableName.constructor variableName.GetType() typeid(variableName)
从名称(字符串)获取类型 Class.forName( typeName ).kotlin Class.forName( typeName ) eval( typeName )(永远不要这样做)
静态定义的运行时类型检查 variableName is TypeName variableName instanceof TypeName typeof variableName === 'typeName'(内部函数)或(对象)variableName instanceof ConstructorName variableName is TypeName
运行时动态类型检查 otherKClass.isInstance( variableName )otherKType.isSubtypeOf() otherClass.isAssignableFrom( variableName.getClass() ) otherType.IsAssignableFrom( variableName.GetType() )
不安全的变窄(又名下沉) val n: NarrowType = widerVar as NarrowType; NarrowType n = (NarrowType)widerVar; variableName as TypeName(仅限 TypeScript) NarrowType n = (NarrowType)widerVar;
安全变窄(下沉或null) val n: NarrowType? = widerVar as? NarrowType; NarrowType n? = widerVar as NarrowType; dynamic_cast<NarrowType>( widerVar )
有条件地缩小范围 variableName is TypeName func(x: unknown): x is TypeNameguard 函数(仅限 TypeScript) widerVar is TypeName n