关于Kotlin中Int :: class.java.isInstance()的混淆

时间:2017-09-06 03:31:36

标签: kotlin

Int::class.java.isInstance(4)的结果是错误的。

但是String::class.java.isInstance("aa")是真的。

Int类型检查函数的正确方法是什么。

fun <T> castValue(v: Any?, clazz: Class<T>): T? {
  if (v != null && clazz.isInstance(v) return v as T
  return null
}

val result = castValue(4, Int::class.java)

3 个答案:

答案 0 :(得分:2)

您可以使用reified类型参数来实现此目的:

inline fun <reified T> cast(value:Any?): T? = value as? T

并称之为:

cast<Boolean>(false)

答案 1 :(得分:1)

::class.java是调用Java方法而不是Kotlin。

如果要测试类型,请使用is

val isInt = 1 is Int // true

如果您想尝试演员,请使用as?

val num = unknown as? Int // null if it is not Int

答案 2 :(得分:0)

问题是Int::class引用原始int类型,但值是带框的Integer类型。

解决方法是使用Integer::class而不是Int::class,因为这将引用盒装的Java类型。

为了更通用,您可以使用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中没有内置方法来获取基本类型的包装类。

@Suppress("UNCHECKED_CAST")
fun <T> castValue(v: Any?, clazz: Class<T>): T? =
    v?.takeIf(primitiveToWrapper(clazz)::isInstance) as T?
相关问题