我们在使用ORM框架时,从数据库中查询数据,然后返回一个集合或者其他类型。但是,框架怎么知道我要获取的是什么类型的呢?比如:List<Date>、Map<String,Integer>等,框架怎么知道我要返回的集合中的元素类型是Date、String、Integer呢?可能你会说是使用反射的方式,话是不错,但说反射毕竟太笼统了。我们可以从Hibernate框架的源码中获取点经验,既然Hibernate可以实现自动类型转换,那我们为何不向前辈学习呢?! 自动类型转换的方法大致如下:
public class TestGer {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Method method = TestGer.class.getMethod("test", List.class); //获取方法实例
Type[] types = method.getGenericParameterTypes(); //获得原始类型参数
ParameterizedType pt = (ParameterizedType) types[0];//获得的原始类型参数的是一个type类型的数组,数组的长度为实际方法参数的个数
System.out.println(pt.getActualTypeArguments()[0]);//打印实际类型参数
System.out.println(pt.getRawType());//打印原始类型
System.out.println("-------------------------");
Method method2 = TestGer.class.getMethod("testMap", Map.class);
Type[] types2 = method2.getGenericParameterTypes();
ParameterizedType pt2 = (ParameterizedType) types2[0];
Type[] tps2 = pt2.getActualTypeArguments(); //实际类型参数长度为2,map包括key和value
System.out.println(tps2[0]); //map的key类型
System.out.println(tps2[1]);//map的value类型
System.out.println(pt2.getRawType()); //map的原始类型
}
public void test(List<Date> date){
}
public void testMap(Map<String,Integer> map){
}
}
关键点:上面的方式是通过方法的类型参数获取实际参数的类型的,换句话说也就是:我们不能通过如下方式获取实际参数的类型。
List<Date> date = new ArrayList<Date>();
TypeVariable<?>[] clazz = date.getClass().getTypeParameters();
我们没办法直接通过字节码获得集合中的实际参数化的类型,编译器在编译成字节码后会去掉集合中参数化类型信息。
eg:
List<Date> dList = new ArrayList<Date>();
List<String> sList = new ArrayList<String>();
System.out.println(dList.getClass() == sList.getClass());
上面的返回值是true,因为编译器把源代码编译成字节码时已经去掉了参数化的类型信息。
以我目前所知道的,我们只能通过方法签名获取集合中实际参数类型。Method类API中提供的有相关获取原始类型的方法,有兴趣的可以查阅。 Method API的getGenericParameterTypes()方法返回的是Type类型的数组,而Type有很多子类,比如大名鼎鼎的Class类也是Type的子类,也正如《Java编程思想》中所说type可以等同于class。而在这里我们需要用的是Type的子类ParameterizedType,ParameterizedType代表参数化的类型。我们可以通过其中的方法获取实际参数化的类型和原始类型。
ORM框架类型自动转换原理
最新推荐文章于 2024-12-16 16:01:31 发布
ORM框架在处理数据库查询时能自动将数据转换为指定类型,如List<Date>、Map<String, Integer>。其原理主要涉及Java反射机制,通过Method类获取方法的参数类型。在Hibernate框架中,通过ParameterizedType获取实际类型参数。由于编译后的字节码不包含集合参数化类型信息,所以不能直接通过对象的Class获取。因此,只能通过方法签名来获取实际的参数类型。"
110878987,7286491,CDN技术详解:静态加速与动态加速,"['CDN', '网络优化', '流媒体', '动态加速', '静态加速']

944

被折叠的 条评论
为什么被折叠?



