提问人:Kun.tito 提问时间:3/9/2022 更新时间:3/9/2022 访问量:751
在 Kotlin 中,“::class.simpleName”是做什么的?
In Kotlin, what does "::class.simpleName" do?
问:
val var1: Any = "Carmelo Anthony"
我的印象是,当我执行以下操作时,会返回对象
的变量类型:::class.simpleName
val var1Type = var1::class.simpleName
print(var1Type)
我得到和不String
Any
但是当我这样做时
val var2: String = var1
我得到一个Type mismatch: inferred type is Any but String was expected
答:
6赞
Dai
3/9/2022
#1
- 在 Kotlin 中,运算符以 2 种形式存在:
::class
TypeName::class
- 它返回静态类型TypeName
的KClass
对象。variableName::class
- 它返回一个KClass
对象,对应于运行时类型 ,而不是 的静态类型。(Kotlin 在他们的文档中称其为“绑定类型”)。variableName
variableName
- 在您的例子中,运行时类型为 ,但静态类型为 。
var1
String
Any
- 所以返回 for ,而不是 。
var1::class
KClass
String
Any
- 所以返回 for ,而不是 。
- 但是 Kotlin 的类型系统,就像大多数静态类型语言一样,不允许隐式缩小转换(即,给定一个类型为 的变量,你不能从另一个变量 () 静态类型为 ,因为可能有一个与 完全不兼容的运行时类型,例如一个对象。
var2
String
var2
var3
Any
var3
String
InputStream
- ...即使可以证明(通过手动操作程序),-typed 值将始终是 .
Any
String
- 然而,幸运的是,Kotlin 的类型检查器是现代的,它的“智能转换”功能在使用运算符时遵循类型缩小的范围,这很简洁(TypeScript 也有,我认为任何其他语言都没有)。
is
- 如果您无法使用智能投射,或者可以通过其他方式向自己证明投射是安全的,请使用操作员执行不安全的投射。这样:。
as
var2: String = var1 as String
- (有点令人困惑的是,其他语言用作安全转换的运算符,啊)。
as
- (有点令人困惑的是,其他语言用作安全转换的运算符,啊)。
- 如果您无法使用智能投射,或者可以通过其他方式向自己证明投射是安全的,请使用操作员执行不安全的投射。这样:。
- ...即使可以证明(通过手动操作程序),-typed 值将始终是 .
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 TypeName guard 函数(仅限 TypeScript) |
widerVar is TypeName n |
评论
var1
Any
val var2: String = var1 as String