很早之前写过利用泛型和反射机制抽象DAO ,对其中获取子类泛型的class一直不是很理解。关键的地方是HibernateBaseDao的构造方法中的

  1. Type genType = getClass().getGenericSuperclass();
  2. Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  3. entityClass =  (Class)params[0];

但是这个相对子类才会有用,而且那篇文章的HibernateBaseDao还不是abstract,如果一不小心实例化的话就会报异常。感觉java中通过反射取泛型的class还是挺复杂的,不过一旦取到的话就可以做很多事情了。

改进的例子和测试:

1.先定义接口(这里写的比较简单就一个方法,具体可以再增加)

  1. public interface BaseDao<T> {
  2. T get(String id);
  3. }

2.定义抽象类实现接口

  1. import java.lang.reflect.ParameterizedType;
  2. import java.lang.reflect.Type;
  3. public abstract class HibernateBaseDao<T> implements BaseDao<T> {
  4. private Class<T> entityClass;
  5. /**
  6. * 这个通常也是hibernate的取得子类class的方法
  7. *
  8. * @author "yangk"
  9. * @date 2010-4-11 下午01:51:28
  10. */
  11. public HibernateBaseDao() {
  12. Type genType = getClass().getGenericSuperclass();
  13. Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  14. entityClass = (Class) params[0];
  15. }
  16. @Override
  17. public T get(String id) {
  18. try {
  19. return entityClass.newInstance();
  20. } catch (InstantiationException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. } catch (IllegalAccessException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. }
  27. return null;
  28. }
  29. }

子类的构造函数会调用父类的构造函数,所以当子类实例化的时候,父类的entityClass 已经得到了T.class。

3.定义一个entity

  1. public class Entity {
  2. private String name;
  3. public String getName() {
  4. return name;
  5. }
  6. public void setName(String name) {
  7. this.name = name;
  8. }
  9. }

4.定义entity的DAO

  1. public class EntityDao extends HibernateBaseDao<Entity> {
  2. public void otherOperation() {
  3. }
  4. }

可以在里面定义父类没有的,针对具体子类特殊的方法。

5.测试

  1. import static org.junit.Assert.assertNotNull;
  2. import org.junit.After;
  3. import org.junit.AfterClass;
  4. import org.junit.Before;
  5. import org.junit.BeforeClass;
  6. import org.junit.Test;
  7. public class JunitTest {
  8. @BeforeClass
  9. public static void setUpClass() throws Exception {
  10. }
  11. @AfterClass
  12. public static void tearDownClass() throws Exception {
  13. }
  14. @Before
  15. public void setUp() {
  16. }
  17. @After
  18. public void tearDown() {
  19. }
  20. /**
  21. * Test of getEClass method, of class tmp.
  22. */
  23. @Test
  24. public void testNewClass() {
  25. EntityDao testDao = new EntityDao();
  26. Entity e = testDao.get(null);
  27. assertNotNull(e);
  28. }
  29. }

运行,可以看到测试顺利通过。

注意:上面子类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的更多相关文章

  1. Java反射给泛型集合赋值

    Java反射给泛型集合赋值 泛型 Java泛型简单描述下: 比如创建一个List集合,我想在里边只放Student对象信息,就需要写成 List<Student> studentList ...

  2. 深入分析Java反射(三)-泛型

    前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...

  3. Java反射,泛型在Json中的运用

    最近项目中遇到了Json数据自动获取的功能,不然令人想起java的反射,已经很长时间没复习java了正好一块连java的这一块内容一起过一遍.java中的反射无疑就相当于java开发者的春天,在众多的 ...

  4. 2015第22周六Java反射、泛型、容器简介

    Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...

  5. java 反射和泛型

    反射 在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问.检测和修改它本身状态或行为的一种能力.[1]用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为. 要注意术 ...

  6. java 反射和泛型-反射来获取泛型信息

    通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public.获得Field对象后都可以使用getType()来获取其类型. Class&l ...

  7. 关于java反射获取泛型

    public class Test<T> { private final TypeToken<T> typeToken = new TypeToken<T>(get ...

  8. java反射获得泛型参数getGenericSuperclass():获取到父类泛型的类型

    public class Person<T> { } import java.lang.reflect.ParameterizedType; import java.lang.reflec ...

  9. Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题

    在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...

随机推荐

  1. 使用while和read命令读取文件内容

    转:使用while和read命令读取文件内容 1.准备数据文件 $cat a.txt 200:2 300:3 400:4 500:5 2.用while循环从文件中读取数据 #!/bin/ksh whi ...

  2. linux RPM manager

    RPM manage:rpm2cpio package_name | cpio -id #将一个rpm包解压至当前目录rpm -qi package_name #查看一个已安装的rpm包信息rpm - ...

  3. 为小米(红米)6A解锁_ROOT_安装天下游虚拟定位教程_已亲身验证通过!附图

    第一步骤: 把TeamViewer发给客户 第二步骤: 在自己电脑上购买小米账号:http://shop1.91kami.com/UXWHTEY9KN?cid=1200 要求:(购买邮箱注册账号,需要 ...

  4. 作业20171116 beta2及beta发布 成绩

    申诉 对成绩有疑问或不同意见的同学,请在群里[@杨贵福]. 申诉时间截止2017年12月13日 17:00. 成绩 scrum01 scrum02 scrum03 scrum04 scrum05 sc ...

  5. Visual Studio2013安装过程以及单元测试

    一.安装环境 操作系统版本:Windows10家庭中文版64位 CPU:i5-4200u  1.60GHz 硬盘内存:750G 二.安装版本 Visual Studio2013 三.安装过程 Visu ...

  6. 11.13 Daily Scrum

    今天在实现餐厅列表时,原来使用的百度地图poi搜索接口无法返回餐厅的具体信息. 经过一番周折,找到了一个返回餐厅url的接口.我们调整了一下实现,在点击餐厅列表的某一项点击直接跳到和该餐厅信息有关的网 ...

  7. /var/lib/mysql 的访问权限问题 Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

    mysql 登录不进去 提示Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) she ...

  8. Git学习笔记 第二章

    文件相关操作 修改readme.txt文件,执行 git status 命令查看当前仓库状态 git status 位于分支 master 尚未暂存以备提交的变更: (使用 "git add ...

  9. mybatis逆向工程生成example的问题

    如果不想生成example,在 targetRuntime="MyBatis3" 处修改为  targetRuntime="MyBatis3Simple"  & ...

  10. springframework内BeanUtils源码使用记录一

    package org.springframework.beans; public abstract class BeanUtils /** * Copy the property values of ...