java的反射类型分打开5种类型,如下所示
1.ParameterizedType(参数化类型)
2.GenericArrayType(数组类型)
3.TypeVariable(类型变量)
4.Class(原始类型)
5.WildcardType(通配符类型)
ParameterizedType表示参数化类型,也就是泛型,例如List,Map等类作为参数的类型。
代码如下(示例):
class TestType {
val test :List<String> = arrayListOf()
companion object {
@JvmStatic
fun main(args: Array<String>) {
val declaredField = TestType::class.java.getDeclaredField("test")
val genericType = declaredField.genericType
//sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
print(genericType::class.java.name+"\n")
//java.util.List
print(genericType)
}
}
}
打印日志可以看出 genericType 的类型为 ParameterizedType,
ParameterizedType 有3个方法可以获取到具体类型
getActualTypeArguments()、 getRawType()、 getOwnerType()
getActualTypeArguments
获取泛型中的实际类型,可能会存在多个泛型,例如Map,所以会返回Type[]数组,接下面的代码如下
(genericType as ParameterizedType).let {
val actualTypeArguments = it.actualTypeArguments
repeat(actualTypeArguments.size){
//class java.lang.String
print(actualTypeArguments[it])
}
}
可以看出 getActualTypeArguments 是获取泛型的类型。
getRawType
获取声明泛型的类或者接口,也就是泛型中<>前面的那个值;
(genericType as ParameterizedType).let {
val rawType = it.rawType
//interface java.util.List
print(rawType)
}
可以看出打印出来的为List类型,也就是泛型<>前面的值。
getOwnerType
此方法是获取泛型的拥有者,那么拥有者是个什么意思?
拥有者”表示的含义–内部类的“父类”,如Map 就是 Map.Entry的拥有者。当没有的时候,会返回 null 。
(genericType as ParameterizedType).let {
val rawType = it.rawType
//null
print(rawType)
}
泛型数组类型,例如E[] 、T[]、List[] (可以理解为包含泛型变量的数组)获取到的type的就是 GenericArrayType
注意:list[] 、String[]不是该类型,他们不包含泛型,他们直接是特殊的Class类型(Class类型在后面讲到)
class TestType {
val list :Array<List<String>> = arrayOf()
companion object {
@JvmStatic
fun main(args: Array<String>) {
val declaredField =TestType::class.java.getDeclaredField("list")
val genericType = declaredField.genericType
//sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
print(genericType::class.java.name+"\n")
//java.util.List[]
print(genericType.toString()+"\n")
}
}
}
可以看到这时候拿到的genericType 类型为 GenericArrayTypeImpl
该类只包含一个方法,就是 getGenericComponentType
getGenericComponentType
该方法返回脱离数组的类型,即只会脱去最右边的[],返回剩下的值;
例如List[][] 会返回 List[]
(genericType as? GenericArrayType)?.let {
val genericComponentType = it.genericComponentType
//java.util.List
print(genericComponentType)
}
可以看到会返回 List
泛型的类型变量,指的是List、Map中的T,K,V等值 或者类实现了泛型,对应的变量指明了类的对象,实际的Java类型是TypeVariableImpl(TypeVariable的子类);此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;
class TestType<T : Number,Serializable>{
val data : T? = null
companion object {
@JvmStatic
fun main(args: Array<String>) {
val declaredField = TestType::class.java.getDeclaredField("data")
val genericType = declaredField.genericType
//sun.reflect.generics.reflectiveObjects.TypeVariableImpl
print(genericType::class.java.name+"\n")
//T
print(genericType.toString()+"\n")
}
}
}
可以看到这时候返回了 TypeVariableImpl 类型。TypeVariableImpl 也包含了3个方法。getBounds()、getGenericDeclaration()、getName()
getBounds
该方法获取该泛型的上限,也就是泛型类中extend右边的值。如果没有显式限制,那默认是Object。
(genericType as? TypeVariable<*>)?.let {
val bounds = it.bounds
//class java.lang.Number
repeat(bounds.size){
print(bounds[it].toString() + "\n")
}
}
可以看到bounds是一个数组,是因为限制是可以多限制(java通过 &符号相连接),所以会返回一个数组
getGenericDeclaration
获取声明该类型变量实体,也就是TestType中的TestType;意思 返回该变量所在的类。
(genericType as? TypeVariable<*>)?.let {
val genericDeclaration = it.genericDeclaration
//class com.ming.algorithm.test.TestType
print(genericDeclaration)
}
因为该变量在 TestType 中声明,所以返回了class com.ming.algorithm.test.TestType
getName
获取类型变量在源码中定义的名称;即泛型的名称
(genericType as? TypeVariable<*>)?.let {
val name = it.name
//T
print(name)
}
因为该变量在类中是以 T 声明,所以返回是 T
Class 是Type接口的实现类,是我们工作中常用到的一个对象,也就是普通属性的命名。
class TestType<T : Number,Serializable>{
val data : String? = null
companion object {
@JvmStatic
fun main(args: Array<String>) {
val declaredField = TestType::class.java.getDeclaredField("data")
val genericType = declaredField.genericType
//java.lang.Class
print(genericType::class.java.name+"\n")
//class java.lang.String
print(genericType.toString()+"\n")
}
}
}
可以看到平常命名的属性 返回的 Type 就是 java.lang.Class
?—通配符表达式,表示通配符泛型,但是WildcardType并不属于Java-Type中的一钟, 获取到的 type 依然是 ParameterizedTypeImpl ;例如:java写法 List extends Number> 和 List super Integer>, kotlin 写法 out in 写法。也就是可读和可放的关系。
具体可参考:https://blog.csdn.net/u011288271/article/details/107318507 该文章。
class TestType<T : Number,Serializable>{
val data : List<out String>? = null
companion object {
@JvmStatic
fun main(args: Array<String>) {
val declaredField = TestType::class.java.getDeclaredField("data")
val genericType = declaredField.genericType
//sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
print(genericType::class.java.name+"\n")
//java.util.List
print(genericType.toString()+"\n")
}
}
}
可以看到获取到的类型为 ParameterizedTypeImpl,我们可以通过 actualTypeArguments 继续获取该参数。得到该参数的class 为 WildcardType
(genericType as? ParameterizedType)?.let {
val actualTypeArguments = it.actualTypeArguments
//class java.lang.Number
repeat(actualTypeArguments.size){
print(actualTypeArguments[it]::class.java.toString() + "\n")
}
}
wildcardType 包含2个方法。getUpperBounds()、getLowerBounds();
getUpperBounds
获取泛型变量的上边界(extends),kotlin(in)
getLowerBounds
获取泛型变量的上边界(super),kotlin(out)
泛型只能作用于类(Class),构造方法(Constructor),和方法(Method)。 因为 GenericDeclaration;含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型),如上面所示。
所以 Field 中并没有声明泛型,而是在使用泛型而已,需要在类或者方法有泛型,才可以使用。
以上就是对于泛型不同使用,解析获取实际Class的解析。实际按照要求进行解析。封装好的方法有,如Gson的 G s o n Gson GsonTypes.canonicalize
G s o n Gson GsonTypes.getRawType(type)。 可以直接使用便可以获取到真实的class