泛型的作用
Java中的泛型采用的是泛型擦除机制。java中的泛型仅仅是给JVM虚拟机使用的,是为了保证数据的安全和免去强制转化的操作。JVM虚拟机在编译的时候会自动的依据泛型进行相应的类型转化操作,但是,在编译完成之后,泛型的影子就全都消失了,你可以这样理解,泛型是一个JVM编译的一个规范,它告诉虚拟机这个地方应该这样编译,这个类型应该这样转化,但它仅仅只是一个编译的规范,并不包含在编译的结果中。
所以你用反射直接读取是读取不到的,因为反射操作的是编译好的类模块,而根据我们之前说的就可以了解到这个时候的类模板中是不存在的泛型的类型信息的,因为他们被JVM进行了泛型的类型擦除。
所以为了解决这个问题,java新增了以下的类型,用于保存泛型,通过操作这些类型就可以通过反射来操作泛型。
关于这些类型的解释比较抽象,所以这里就把关于反射操作泛型最常用的操作在以下代码中展出,通过代码和结果可以更直观的了解这些类型。
package com.maple.reflect.demo03;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import org.junit.Test;
/**
* 反射操作常用泛型 参数泛型和返回值泛型
*
* @author MapleSky
*
*/
public class ReflectionAndGeneric {
/**
* 参数
*
* @param map
* @param list
*/
public void method01(Map<String, Integer> map, List<User> list) {
}
public Map<Integer, User> method02() {
return null;
}
/**
* 测试ParameterizedType
*/
@Test
public void testMethod01() throws Exception {
String path = "com.maple.reflect.demo03.ReflectionAndGeneric";
Class<?> clazz = Class.forName(path);
Method method01 = clazz.getDeclaredMethod("method01", Map.class, List.class);
//获取参数中的泛型信息
Type[] genericParameterTypes = method01.getGenericParameterTypes();
for(Type t:genericParameterTypes) {
System.out.println("#"+t);
//获取参数中具体的泛型
if(t instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType)t).getActualTypeArguments();
for(Type genericType : actualTypeArguments) {
System.out.println(" "+genericType);
}
}
}
}
/**
* 测试ParameterizedType
*/
@Test
public void testMethod02() throws Exception {
String path = "com.maple.reflect.demo03.ReflectionAndGeneric";
Class<?> clazz = Class.forName(path);
Method method02 = clazz.getDeclaredMethod("method02");
//获取返回类型的泛型信息
Type genericParameterTypes = method02.getGenericReturnType();
System.out.println("#"+genericParameterTypes);
if(genericParameterTypes instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType)genericParameterTypes).getActualTypeArguments();
for(Type genericType : actualTypeArguments) {
System.out.println(" "+genericType);
}
}
}
}
testMethod01结果如下:
testMethod02结果如下:
你通过分析代码的结果就可以很清楚的了解这些类型的具体用法。关于反射,目前就了解到这个程度已经足够了,以后要想深入学习,可以通过查看各类流行框架的源码来实现。