Kotlin反射调用构造方法时参数类型不匹配问题排查
解决Kotlin反射中基本类型与包装类型不匹配的问题
你遇到的这个NoSuchMethodException问题,核心原因是Java/Kotlin反射系统中,基本类型(如float)和对应的包装类型(如java.lang.Float)是完全不同的Class对象,用包装类型去匹配构造方法的基本类型参数,自然找不到对应的方法。
问题分析
你的argTypes方法中,通过it::class.java获取参数类型:
private fun argTypes(vararg args: Any): Array<Class<*>> { val argTypes = ArrayList<Class<*>>() args.forEach { argTypes.add(it::class.java) } return argTypes.toTypedArray() }
当你传入100F时,这个值在Kotlin中会被自动装箱为java.lang.Float对象,所以it::class.java返回的是java.lang.Float类型;而目标构造方法的参数是基本类型float,对应的Class是float.class(在Kotlin中可以用Float::class.javaPrimitiveType获取),两者不匹配,导致反射找不到构造方法。
解决方案
修改argTypes方法,自动将包装类型转换为对应的基本类型Class。我们可以利用包装类的TYPE字段(比如Float.TYPE就是float.class),或者Kotlin中基本类型的javaPrimitiveType属性来实现:
方案一:基于包装类匹配
private fun argTypes(vararg args: Any): Array<Class<*>> { return args.map { arg -> val clazz = arg::class.java // 根据包装类匹配对应的基本类型Class when (clazz) { java.lang.Float::class.java -> java.lang.Float.TYPE java.lang.Integer::class.java -> java.lang.Integer.TYPE java.lang.Boolean::class.java -> java.lang.Boolean.TYPE java.lang.Long::class.java -> java.lang.Long.TYPE java.lang.Double::class.java -> java.lang.Double.TYPE java.lang.Short::class.java -> java.lang.Short.TYPE java.lang.Byte::class.java -> java.lang.Byte.TYPE java.lang.Character::class.java -> java.lang.Character.TYPE else -> clazz // 非基本类型包装类,直接返回原Class } }.toTypedArray() }
方案二:Kotlin风格的基本类型判断
private fun argTypes(vararg args: Any): Array<Class<*>> { return args.map { arg -> when (arg) { is Float -> Float::class.javaPrimitiveType is Int -> Int::class.javaPrimitiveType is Boolean -> Boolean::class.javaPrimitiveType is Long -> Long::class.javaPrimitiveType is Double -> Double::class.javaPrimitiveType is Short -> Short::class.javaPrimitiveType is Byte -> Byte::class.javaPrimitiveType is Char -> Char::class.javaPrimitiveType else -> arg::class.java } ?: arg::class.java // 兜底,防止javaPrimitiveType为空(实际不会发生) }.toTypedArray() }
为什么这样可行?
- 反射查找构造方法时,必须精确匹配参数的
Class类型,基本类型和包装类型的Class是不同的; - 当调用
newInstance(*args)时,反射系统会自动将包装类对象拆箱为对应的基本类型值,所以不用担心参数传递的兼容性问题。
修改后,你的newInstance方法就能正确找到带有float参数的构造方法了。
内容的提问来源于stack exchange,提问作者hasan demirtaş
相关产品推荐
相关产品推荐

