我想在Java 8中使用反射来重构方法的签名。我遇到了通用方法的一些问题。
特别是,在模板类型声明中,我找不到任何有助于恢复有关“扩展”或“超级”情况的信息。
这是一个基于已知源代码的特定测试用例:
该方法的签名来自源代码:public static <T extends AssertDelegateTarget> T assertThat(T assertion)
首先,是否有一种优雅的方法来重新构成<T extends AssertDelegateTarget>
部分而不必解析字符串?
这是我能够通过反思得到的主要信息:method.toString()
:public static org.assertj.core.api.AssertDelegateTarget org.assertj.core.api.Assertions.assertThat(org.assertj.core.api.AssertDelegateTarget)
method.toGenericString()
:public static <T> T org.assertj.core.api.Assertions.assertThat(T)
“扩展AssertDelegateTarget”发生了什么?method.getReturnType.toString()
:interface org.assertj.core.api.AssertDelegateTarget
method.getGenericParameterTypes()[0].getTypeName()
:T
根据上面的反射信息,我可以假设T和AssertDelegateTarget之间存在关系,但是我如何知道它是“扩展”还是“超级”?
最佳答案
您已经有Method
对象。从此处开始,获取使用the getTypeParameters
method在方法上声明的类型参数,该参数返回TypeVariable<Method>[]
。这是在方法中声明的类型参数的数组。在这种情况下,它只有一个类型参数,因此返回的数组只有一个元素。TypeVariable
interface具有检索名称T
的方法getName
和检索边界getBounds
的方法。 getBounds
方法返回一个Type[]
。您可以确定这里的任何边界都是上限,因为类型变量的声明不允许使用super
,而只能使用extends
。
在这种情况下,Type
变量只是Class
的AssertDelegateTarget
对象。
现在,您可以根据以上信息重新构建"<T extends AssertDelegateTarget>"
字符串。如果Type[]
为非空,则仅使用“扩展”。如果存在多个界限,则可以在它们之间放置一个逗号,例如T extends Bound1, Bound2
。