kotlin - 有没有办法从'String'转换为'KType'?
问题描述
简单地说,我想要一个类似的功能:
fun <T> convert(val foo: String, fooT: KType) : T {
...?
}
For Int
,它会返回foo.toInt()
, for Double
, foo.toDouble()
, 和一些未知的类型,只是抛出一个异常。我认为为我期望的类型创建自己的 switch 语句并不难,但出于好奇 - 已经有办法了吗?
解决方案
推荐方式
不幸的是,没有简单的通用方法,因为我们处理的不是转换,而是方法调用。这将是我的方法:
fun <T> convert(str: String, type: KType) : T {
val result: Any = when (type.jvmErasure)
{
Long::class -> str.toLong()
Int::class -> str.toInt()
Short::class -> str.toShort()
Byte::class -> str.toByte()
...
else -> throw IllegalArgumentException("'$str' cannot be converted to $type")
}
return result as T // unchecked cast, but we know better than compiler
}
用法:
@UseExperimental(ExperimentalStdlibApi::class)
fun main() {
val int = convert<Int>("32", typeOf<Int>())
println("converted: $int")
}
除了KType
参数,您还可以使用 aClass<T>
并使函数具体化,因此它可以被称为convert<Int>("32")
甚至"32".toGeneric<Int>()
.
铁杆方式
虽然没有简单的方法,但可以使用大量反射并依赖实现细节来访问类型。为此,我们可以从KType
对象中提取类型名称,找到匹配的扩展方法(在不同的类中),并使用反射调用它。
我们必须使用to*OrNull()
而不是to*()
,因为后者是内联的,不会被反射找到。此外,我们需要借助 Java 反射——此时,Kotlin 反射会抛出UnsupportedOperationException
所涉及的类型。
我不建议在生产代码中这样做,因为它效率低下并且可能会与未来的标准库版本中断,但这是一个很好的实验:
fun convert(str: String, type: KType): Any {
val conversionClass = Class.forName("kotlin.text.StringsKt")
// here, the to*OrNull() methods are stored
// we effectively look for static method StringsKt.to*OrNull(String)
val typeName = type.jvmErasure.simpleName
val funcName = "to${typeName}OrNull" // those are not inline
val func = try {
conversionClass.getMethod(funcName, String::class.java) // Java lookup
} catch (e: NoSuchMethodException) {
throw IllegalArgumentException("Type $type is not a valid string conversion target")
}
func.isAccessible = true // make sure we can call it
return func.invoke(null, str) // call it (null -> static method)
?: throw IllegalArgumentException("'$str' cannot be parsed to type $type")
}
推荐阅读
- sql - 有没有办法查看PostgreSQL的后端处理?
- windows - 如何在 MinGW/MSYS2 上安装静态 libz.dll.a、libssl.dll.a 等?
- javascript - Javascript 内容弹出按钮
- jupyter-notebook - 如何在 pytorch 中将第二个 gpu 设置为 juptyer 笔记本中的默认值?
- here-api - 从 Here.js 开始创建新的 MapView 获取 TypeError
- android - 接收 TypeError: undefined is not a function (near'...posts.map...') React-Native / Rails 6.0 API
- git - 修改 gitlab 提交
- regex - 匹配包含正则表达式字符的变量
- javascript - Javascript精度解决方案?
- xamarin - 如何在 xamarin 的另一个表单上更改按钮背景颜色