- In Kotlin, the
::class
operator exists in 2 forms:
- 在您的例子中,
var1
的运行时tytpe为String
,但静态类型为Any
.
- 但是,与大多数静态类型语言一样,Kotlin的类型系统不允许隐式缩小转换(即,给定一个类型为
String
的变量var2
,您不能从另一个静态类型为Any
的变量(var3
)分配给var2
,因为var3
could的运行时类型与String
完全不兼容,例如InputStream
对象.
In context:
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)
}
如果您熟悉其他语言,那么下面是一个不完整的等效操作及其语法表:
|
Kotlin |
Java |
JavaScript |
C# |
C++ |
Get static type |
TypeName::class |
TypeName.class |
ConstructorName |
typeof(TypeName) |
typeid(TypeName) |
Get runtime type |
variableName::class |
variableName.getClass() |
typeof variableName (intrinsics) variableName.constructor (objects) |
variableName.GetType() |
typeid(variableName) |
Get type from name (string) |
Class.forName( typeName ).kotlin |
Class.forName( typeName ) |
eval( typeName ) (never do this) |
|
|
Statically-defined runtime type check |
variableName is TypeName |
variableName instanceof TypeName |
typeof variableName === 'typeName' (intrinsics) or variableName instanceof ConstructorName (objects) |
variableName is TypeName |
|
Runtime dynamic type check |
otherKClass.isInstance( variableName ) or otherKType.isSubtypeOf() |
otherClass.isAssignableFrom( variableName.getClass() ) |
|
otherType.IsAssignableFrom( variableName.GetType() ) |
|
Unsafe narrowing (aka downcast) |
val n: NarrowType = widerVar as NarrowType; |
NarrowType n = (NarrowType)widerVar; |
variableName as TypeName (TypeScript only) |
NarrowType n = (NarrowType)widerVar; |
|
Safe narrowing (downcast or null ) |
val n: NarrowType? = widerVar as? NarrowType; |
|
|
NarrowType n? = widerVar as NarrowType; |
dynamic_cast<NarrowType>( widerVar ) |
Conditional narrowing in scope |
variableName is TypeName |
|
func(x: unknown): x is TypeName guard functions (TypeScript only) |
widerVar is TypeName n |
|