Kotlin-TypeReference T无法获得Class *对于类型参数 [英] Kotlin - TypeReference<T> Cannot obtain Class<*> For Type Arguments
问题描述
我已经创建了与 TypeReference< T>
等效的Kotlin,如下所示:
I've created a Kotlin equivalent of TypeReference<T>
like so:
abstract class TypeReference<T> : Comparable<T> {
val type: Type get() = getGenericType()
val arguments: List<Type> get() = getTypeArguments()
final override fun compareTo(other: T): Int {
return 0
}
private fun getGenericType(): Type {
val superClass = javaClass.genericSuperclass
check(superClass !is Class<*>) {
"TypeReference constructed without actual type information."
}
return (superClass as ParameterizedType).actualTypeArguments[0]
}
private fun getTypeArguments(): List<Type> {
val type = getGenericType()
return if (type is ParameterizedType) {
type.actualTypeArguments.toList()
} else emptyList()
}
}
为了获得泛型类型及其参数的 Class< *>
,我还创建了以下扩展函数(这是我认为问题出在哪里,因为这是堆栈跟踪失败的地方.)
In order to obtain Class<*>
of the generic type and its arguments, I've also created the following extension function (and this is where I believe the problem lies, since this is where the stack trace fails).
fun Type.toClass(): Class<*> = when (this) {
is ParameterizedType -> rawType.toClass()
is Class<*> -> this
else -> Class.forName(typeName)
}
我正在像这样进行单元测试:
I'm unit testing this like so:
@Test
fun `TypeReference should correctly identify the List of BigDecimal type`() {
// Arrange
val expected = List::class.java
val expectedParameter1 = BigDecimal::class.java
val typeReference = object : TypeReference<List<BigDecimal>>() {}
// Act
val actual = typeReference.type.toClass()
val actualParameter1 = typeReference.arguments[0].toClass()
// Assert
assertEquals(expected, actual)
assertEquals(expectedParameter1, actualParameter1)
}
我认为问题在于扩展功能 else->抛出的Class.forName(typeName)
:
The problem I think, lies in the extension function else -> Class.forName(typeName)
as it throws:
java.lang.ClassNotFoundException:吗?扩展java.math.BigDecimal
java.lang.ClassNotFoundException: ? extends java.math.BigDecimal
即使它们是通用类型参数,是否还有更好的方法来获取 Type
的 Class< *>
?
Is there a better way to obtain the Class<*>
of a Type
, even when they're generic type parameters?
推荐答案
您需要添加 is WildcardType->...
分支到您的何时
表达式来处理类似的类型?扩展java.math.BigDecimal
(Kotlin等效于 out java.math.BigDecimal
),?
(Kotlin等效于 *
),?超级整数
(Kotlin等效于java.math.Integer 中的):
You need to add is WildcardType -> ...
branch to your when
-expression to handle types like ? extends java.math.BigDecimal
(Kotlin equivalent is out java.math.BigDecimal
), ?
(Kotlin equivalent is *
), ? super Integer
(Kotlin equivalent is in java.math.Integer
):
fun Type.toClass(): Class<*> = when (this) {
is ParameterizedType -> rawType.toClass()
is Class<*> -> this
is WildcardType -> upperBounds.singleOrNull()?.toClass() ?: Any::class.java
else -> Class.forName(typeName)
}
请注意,在此实现中,单个上限类型将被解析为其上限,但所有其他通配符类型(包括多个上限类型)将解析为 Class< Object>
Note that in this implementation single upper bound types will be resolved as its upper bound, but all other wildcard types (including multiple upper bounds types) will be resolved as Class<Object>
这篇关于Kotlin-TypeReference T无法获得Class *对于类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!