java 反射 子类泛型的class
很早之前写过利用泛型和反射机制抽象DAO ,对其中获取子类泛型的class一直不是很理解。关键的地方是HibernateBaseDao的构造方法中的
- Type genType = getClass().getGenericSuperclass();
- Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
- entityClass = (Class)params[0];
但是这个相对子类才会有用,而且那篇文章的HibernateBaseDao还不是abstract,如果一不小心实例化的话就会报异常。感觉java中通过反射取泛型的class还是挺复杂的,不过一旦取到的话就可以做很多事情了。
改进的例子和测试:
1.先定义接口(这里写的比较简单就一个方法,具体可以再增加)
- public interface BaseDao<T> {
- T get(String id);
- }
2.定义抽象类实现接口
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- public abstract class HibernateBaseDao<T> implements BaseDao<T> {
- private Class<T> entityClass;
- /**
- * 这个通常也是hibernate的取得子类class的方法
- *
- * @author "yangk"
- * @date 2010-4-11 下午01:51:28
- */
- public HibernateBaseDao() {
- Type genType = getClass().getGenericSuperclass();
- Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
- entityClass = (Class) params[0];
- }
- @Override
- public T get(String id) {
- try {
- return entityClass.newInstance();
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
- }
子类的构造函数会调用父类的构造函数,所以当子类实例化的时候,父类的entityClass 已经得到了T.class。
3.定义一个entity
- public class Entity {
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
4.定义entity的DAO
- public class EntityDao extends HibernateBaseDao<Entity> {
- public void otherOperation() {
- }
- }
可以在里面定义父类没有的,针对具体子类特殊的方法。
5.测试
- import static org.junit.Assert.assertNotNull;
- import org.junit.After;
- import org.junit.AfterClass;
- import org.junit.Before;
- import org.junit.BeforeClass;
- import org.junit.Test;
- public class JunitTest {
- @BeforeClass
- public static void setUpClass() throws Exception {
- }
- @AfterClass
- public static void tearDownClass() throws Exception {
- }
- @Before
- public void setUp() {
- }
- @After
- public void tearDown() {
- }
- /**
- * Test of getEClass method, of class tmp.
- */
- @Test
- public void testNewClass() {
- EntityDao testDao = new EntityDao();
- Entity e = testDao.get(null);
- assertNotNull(e);
- }
- }
运行,可以看到测试顺利通过。
注意:上面子类DAO的写法public class EntityDao extends HibernateBaseDao<Entity>
一定要在父类后面带上泛型,负责编译就会出错。
附:这是泛型擦拭法使得Generic无法获取自己的Generic Type类型。实际上BadClass<String>()实例化以后Class里面就不包括T的信息了,对于Class而言T已经被擦拭为Object,而真正的T参数被转到使用T的方法(或者变量声明或者其它使用T的地方)里面(如果没有那就没有存根),所以无法反射到T的具体类别,也就无法得到T.class。而getGenericSuperclass()是Generic继承的特例,对于这种情况子类会保存父类的Generic参数类型,返回一个ParameterizedType,这时可以获取到父类的T.class了,这也正是子类确定应该继承什么T的方法。
java 反射 子类泛型的class的更多相关文章
- Java反射给泛型集合赋值
Java反射给泛型集合赋值 泛型 Java泛型简单描述下: 比如创建一个List集合,我想在里边只放Student对象信息,就需要写成 List<Student> studentList ...
- 深入分析Java反射(三)-泛型
前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...
- Java反射,泛型在Json中的运用
最近项目中遇到了Json数据自动获取的功能,不然令人想起java的反射,已经很长时间没复习java了正好一块连java的这一块内容一起过一遍.java中的反射无疑就相当于java开发者的春天,在众多的 ...
- 2015第22周六Java反射、泛型、容器简介
Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...
- java 反射和泛型
反射 在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问.检测和修改它本身状态或行为的一种能力.[1]用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为. 要注意术 ...
- java 反射和泛型-反射来获取泛型信息
通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public.获得Field对象后都可以使用getType()来获取其类型. Class&l ...
- 关于java反射获取泛型
public class Test<T> { private final TypeToken<T> typeToken = new TypeToken<T>(get ...
- java反射获得泛型参数getGenericSuperclass():获取到父类泛型的类型
public class Person<T> { } import java.lang.reflect.ParameterizedType; import java.lang.reflec ...
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...
随机推荐
- Linux系统安装IDS(snort工具)
第一步:预装daq所需程序 snort使用数据采集器(daq)监听防火墙数据包队列,所以按照daq.需预装的程序有:flex.bison.libcap. sudo apt-get install fl ...
- .Net版本依赖之坑引发的搜查
前言 今天上午,一个客户反馈XX消息没有推送到第三方链接.于是我查看了推送日志列表,并没有今天的.接着登录服务器查询文件日志,看到了记录.我们的代码步骤是消息先推送到消息队列,消费消息队列时,记录文件 ...
- PMO在组织中实现价值应做的工作
PMO在组织中实现价值应做的工作 研发人员及项目经理常常对PMO有反感情绪,认为其不熟悉业务流程与技术.经常要求项目经理和研发人员提交形式化的材料,只审批和监控,不能为项目提供良好的服务.在很多企业, ...
- Quartz_配置
quartz_jobs.xml job 任务 其实就是1.x版本中的<job-detail>,这个节点是用来定义每个具体的任务的,多个任务请创建多个job节点即可 name(必填) 任务名 ...
- webpack笔记
打包 img src src 必须以 点(.) 开始,才能被打包. 如: ./img/logo.png ../img/logo.png 使用 process a.js window.Base_Url ...
- mysql操作命令梳理(4)-grant授权和revoke回收权限
在mysql维护工作中,做好权限管理是一个很重要的环节.下面对mysql权限操作进行梳理: mysql的权限命令是grant,权限撤销的命令时revoke:grant授权格式:grant 权限列表 o ...
- windows如何查看电脑开关机记录
如何查看电脑开关机记录 (一)如果你只是想查看一下,从昨天关机到今天开机之间有没有人使用我的计算机,在“开始”菜单的运行”中输入“eventvwr.msc”,或者是按下"开始菜单" ...
- vue项目环境搭建
安装node.js $ npm install -g vue-cli $ vue init webpack my-project ?Project name ?Project description ...
- 变量 var &函数new
声明变量 变量:变量是存储信息的容器,创建变量通常称为"声明"变量 变量必须以字母开头(小驼峰式myName): 变量也能以 $ 和 _ 符号开头(不过我们不推荐这么做): 变量名 ...
- Linux实践三:程序破解
一.汇编指令机器码 二.反汇编与十六进制编程器 三.可执行文件的基本格式 hexdump -x login 用16进制数字显示login内容 objdump -x login 显示login中各个段以 ...