我正在尝试在 Kotlin 中测试一般类型。
if (value is Map<String, Any>) { ... }
但编译器报错如下:
无法检查已擦除类型的实例:jet.Map
对于普通类型的检查可以正常工作。
if (value is String) { ... }
使用的是 Kotlin 0.4.68 版本。
我在这里漏掉了什么?
我正在尝试在 Kotlin 中测试一般类型。
if (value is Map<String, Any>) { ... }
但编译器报错如下:
无法检查已擦除类型的实例:jet.Map
对于普通类型的检查可以正常工作。
if (value is String) { ... }
使用的是 Kotlin 0.4.68 版本。
我在这里漏掉了什么?
if (value is Map<*, *>) {...}
我认为这是更合适的方式
inline fun <reified T> tryCast(instance: Any?, block: T.() -> Unit) {
if (instance is T) {
block(instance)
}
}
使用方法
// myVar is nullable
tryCast<MyType>(myVar) {
// todo with this e.g.
this.canDoSomething()
}
另一种更短的方法
inline fun <reified T> Any?.tryCast(block: T.() -> Unit) {
if (this is T) {
block()
}
}
使用方法
// myVar is nullable
myVar.tryCast<MyType> {
// todo with this e.g.
this.canDoSomething()
}
something as? String
”不是一样的吗?注意as
后面有问号? - Dalibor Filusas?
,对吗。 - stkJVM会删除泛型类型信息。但是Kotlin拥有具体化的泛型。如果你有一个泛型类型T,你可以将内联函数的类型参数T标记为具体化,这样它就能在运行时进行检查。
因此,你可以这样做:
inline fun <reified T> checkType(obj: Object, contract: T) {
if (obj is T) {
// object implements the contract type T
}
}
checkType()
的例子吗?我不确定第二个参数应该传什么。 - Michael OsofskycheckType(myMapOfStrings, Map<String, Any>)
- Peter Graham这是我使用的:
// Use this value if it is of type T, or else use defaultValue
inline fun <reified T> Any?.useIfTypeOrDefault(defaultValue: T) =
if (this is T) this else defaultValue
使用方法(kotest):
val map = mapOf("foo" to listOf("cheese"), "bar" to 666)
map["foo"].useIfTypeOrDefault<List<String>>(emptyList()).firstOrNull() shouldBe "cheese"
map["bar"].useIfTypeOrDefault<List<String>>(emptyList()).firstOrNull() shouldBe null
map["foo"].useIfTypeOrDefault<Number>(-1) shouldBe -1
map["bar"].useIfTypeOrDefault<Number>(-1) shouldBe 666
我会提供一个解决方案,但我认为它还算干净、比较好
try{
(value as Map<String,Any>?)?.let { castedValue ->
doYourStuffHere() //using castedValue
}
}catch(e: Exception){
valueIsNotOfType() //Map<String,Any>
}
我已经尝试了上面的解决方案,使用tryCast<Array<String?>>
,但在我的具体任务中,由于涉及许多强制转换,这不是一个好主意,因为它会严重降低性能。
这是我最终采用的解决方案 - 手动检查条目并调用方法,就像这样:
fun foo() {
val map: Map<String?, Any?> = mapOf()
map.forEach { entry ->
when (entry.value) {
is String -> {
doSomeWork(entry.key, entry.value as String)
}
is Array<*> -> {
doSomeWork(entry.key, (entry.value as? Array<*>)?.map {
if (it is String) {
it
} else null
}?.toList())
}
}
}
}
private fun doSomeWork(key: String?, value: String) {
}
private fun doSomeWork(key: String?, values: List<String?>?) {
}
Collection<String>
以使其自动转换,该怎么办? - beruicif (it.getSerializable(ARG_PARAMS) is HashMap<*, *>) {it.getSerializable(ARG_PARAMS) as HashMap<String, String>} else null
。所以基本上,如果我检查泛型类型,它会尝试将HashMap<String, Integer>
强制转换为HashMap<String, String>
。我有什么遗漏吗? - Farid