Java获取泛型参数的类型的方法 - 实例讲解
2017-08-21 01:30
826 查看
转载自:http://josh-persistence.iteye.com/blog/2165613
在Java中,我们常常需要获取泛型参数的类型,比如将使用了泛型的Java代码进行序列化和反序列化的时候。
一、在开始试图去获取泛型参数的类型前,可以试着去执行如下的类,看看执行的结果:
Java代码
/**
*
*/
package com.wsheng.aggregator.generic;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
*
* @author Josh Wang(Sheng)
*
* @email swang6@ebay.com
*
*/
public class GenericTest<T> {
public static void main(String[] args) {
GenericTest<String> test = new GenericTest<String>(){}; // 匿名内部类的声明在编译时进行,实例化在运行时进行
Type typeClass1 = test.getClass().getGenericSuperclass();
System.out.println(typeClass1);
if (typeClass1 instanceof ParameterizedType) {
Type actualType1 = ((ParameterizedType)typeClass1).getActualTypeArguments()[0];
System.out.println(actualType1);
} else {
System.out.println(typeClass1 + " is Not ParameterizedType");
}
System.out.println(" ==================================== ");
GenericTest<String> test2 = new GenericTest<String>(); // 所有的泛型类型在运行时都是Object类型
Type typeClass2 = test2.getClass().getGenericSuperclass();
System.out.println(typeClass2);
if (typeClass2 instanceof ParameterizedType) {
Type actualType2 = ((ParameterizedType)typeClass2).getActualTypeArguments()[0];
System.out.println(actualType2);
} else {
System.out.println(typeClass2 + " is Not ParameterizedType");
}
}
}
执行的结果是:
Java代码
com.wsheng.aggregator.generic.GenericTest<java.lang.String>
class java.lang.String
====================================
class java.lang.Object
class java.lang.Object is Not ParameterizedType
从执行的结果可以清晰的看到, 使用匿名内部类的方式可以成功的获取到泛型参数的类型,而直接定义的类对象并不能获取到泛型参数的类型,看完下面的介绍便知道根本原因。
二、Java的泛型机制
Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是Object类型)
三、Class类的getGenericSuperClass()方法解读:
Class的该方法,对于带有泛型的class,返回一个ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。ParameterizedType是表示带有泛型参数的类型的Java类型,JDK1.5引入了泛型之后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,所有包含泛型的Class类都会实现这个接口。
注意,实际运用中还要考虑比较多的情况,比如获得泛型参数的个数避免数组越界等。
四、匿名子类又是如何获取到具体的泛型类型?
这要依赖Java的Class字节码中存储的泛型参数信息。如前面所说,Java的泛型机制虽然在运行期间泛型类和非泛型类都相同(都是Object),但是编译java源代码生成的Class文件中还是保存了泛型相关的信息,这些信息被保存在class字节码常量池中,使用了泛型的代码处会生成一个signature签名字段,该签名signature字段指明了这个常量池的地址,于是可从该常量池中获取到具体的类型。
在Java中,我们常常需要获取泛型参数的类型,比如将使用了泛型的Java代码进行序列化和反序列化的时候。
一、在开始试图去获取泛型参数的类型前,可以试着去执行如下的类,看看执行的结果:
Java代码
/**
*
*/
package com.wsheng.aggregator.generic;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
*
* @author Josh Wang(Sheng)
*
* @email swang6@ebay.com
*
*/
public class GenericTest<T> {
public static void main(String[] args) {
GenericTest<String> test = new GenericTest<String>(){}; // 匿名内部类的声明在编译时进行,实例化在运行时进行
Type typeClass1 = test.getClass().getGenericSuperclass();
System.out.println(typeClass1);
if (typeClass1 instanceof ParameterizedType) {
Type actualType1 = ((ParameterizedType)typeClass1).getActualTypeArguments()[0];
System.out.println(actualType1);
} else {
System.out.println(typeClass1 + " is Not ParameterizedType");
}
System.out.println(" ==================================== ");
GenericTest<String> test2 = new GenericTest<String>(); // 所有的泛型类型在运行时都是Object类型
Type typeClass2 = test2.getClass().getGenericSuperclass();
System.out.println(typeClass2);
if (typeClass2 instanceof ParameterizedType) {
Type actualType2 = ((ParameterizedType)typeClass2).getActualTypeArguments()[0];
System.out.println(actualType2);
} else {
System.out.println(typeClass2 + " is Not ParameterizedType");
}
}
}
执行的结果是:
Java代码
com.wsheng.aggregator.generic.GenericTest<java.lang.String>
class java.lang.String
====================================
class java.lang.Object
class java.lang.Object is Not ParameterizedType
从执行的结果可以清晰的看到, 使用匿名内部类的方式可以成功的获取到泛型参数的类型,而直接定义的类对象并不能获取到泛型参数的类型,看完下面的介绍便知道根本原因。
二、Java的泛型机制
Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是Object类型)
三、Class类的getGenericSuperClass()方法解读:
Class的该方法,对于带有泛型的class,返回一个ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。ParameterizedType是表示带有泛型参数的类型的Java类型,JDK1.5引入了泛型之后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,所有包含泛型的Class类都会实现这个接口。
注意,实际运用中还要考虑比较多的情况,比如获得泛型参数的个数避免数组越界等。
四、匿名子类又是如何获取到具体的泛型类型?
这要依赖Java的Class字节码中存储的泛型参数信息。如前面所说,Java的泛型机制虽然在运行期间泛型类和非泛型类都相同(都是Object),但是编译java源代码生成的Class文件中还是保存了泛型相关的信息,这些信息被保存在class字节码常量池中,使用了泛型的代码处会生成一个signature签名字段,该签名signature字段指明了这个常量池的地址,于是可从该常量池中获取到具体的类型。
相关文章推荐
- java获取泛型参数的类型的方法 - 实例讲解
- Java获取泛型参数的类型的方法
- java取得泛型的参数类型(Gson通过借助TypeToken获取泛型参数的类型的方法)
- java再复习——通过反射获取到方法的参数和返回值的泛型类型
- Java获取泛型参数的类型的方法 .
- ParameterizedType获取java泛型参数类型
- Gson通过借助TypeToken获取泛型参数的类型的方法
- ParameterizedType获取java泛型参数类型
- Gson通过借助TypeToken获取泛型参数的类型的方法
- Java利用反射来获取一个方法的 范型化参数 Vector<Integer>的类型
- Gson通过借助TypeToken获取泛型参数的类型的方法(转)
- 尽可能使用泛型方法,除非需要将类型参数用于实例的字段
- Java利用反射来获取一个方法的 范型化参数 Vector<Integer>的类型
- Android:Gson通过借助TypeToken获取泛型参数的类型的方法
- ParameterizedType获取java泛型参数类型
- java中获取泛型参数类型
- java基础-反射 --通过反射 获取泛型实际类型参数
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- Gson通过借助TypeToken获取泛型参数的类型的方法
- Java方法的可变参数类型实例分析