关于Kotlin中Int :: class.java.isInstance()的一个混淆
Int::class.java.isInstance(4)
是false。
但是String::class.java.isInstance("aa")
是真的。
在这样的函数中, Int
types检查的正确方法是什么?
fun castValue(v: Any?, clazz: Class): T? { if (v != null && clazz.isInstance(v) return v as T return null } val result = castValue(4, Int::class.java)
你可以使用reified
types参数来实现这个function:
inline fun cast(value:Any?): T? = value as? T
并像这样调用它:
cast
::class.java
是调用Java方法而不是Kotlin。
如果你想测试的types,使用is
val isInt = 1 is Int // true
如果你想尝试演员,使用as?
val num = unknown as? Int // null if it is not Int
问题是, Int::class
引用了原始的int
types,但是值是盒装的Integer
types。
解决方法是使用Integer::class
而不是Int::class
,因为这将引用盒装的Javatypes。
为了更通用,你可以使用像Apache Commons ClassUtils.primitiveToWrapper()
这样的助手,或者维护一个
fun primitiveToWrapper(clazz: Class<*>): Class<*> = when (clazz) { java.lang.Void.TYPE -> java.lang.Void::class.java java.lang.Boolean.TYPE -> java.lang.Boolean::class.java java.lang.Byte.TYPE -> java.lang.Byte::class.java java.lang.Character.TYPE -> java.lang.Character::class.java java.lang.Short.TYPE -> java.lang.Short::class.java java.lang.Integer.TYPE -> java.lang.Integer::class.java java.lang.Long.TYPE -> java.lang.Long::class.java java.lang.Float.TYPE -> java.lang.Float::class.java java.lang.Double.TYPE -> java.lang.Double::class.java else -> clazz }
查找表自己。 不幸的是,Java或Kotlin没有内置的方法来获取原始types的包装类。
@Suppress("UNCHECKED_CAST") fun castValue(v: Any?, clazz: Class ): T? = v?.takeIf(primitiveToWrapper(clazz)::isInstance) as T?