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 ...
随机推荐
- Verilog对数据进行四舍五入(round)与饱和(saturation)截位
转自https://www.cnblogs.com/liujinggang/p/10549095.html 一.软件平台与硬件平台 软件平台: 操作系统:Windows 8.1 64-bit 开发套件 ...
- 【译】快速起步-JSX简介
react version: 15.5.0 快速起步-JSX简介 思考这个变量申明: const element = <h1>Hello, world!</h1>; 这个有趣的 ...
- 机器学习 第五篇:分类(kNN)
K最近邻(kNN,k-NearestNeighbor)算法是一种监督式的分类方法,但是,它并不存在单独的训练过程,在分类方法中属于惰性学习法,也就是说,当给定一个训练数据集时,惰性学习法简单地存储或稍 ...
- UWP简单示例(二):快速开始你的3D编程
准备 IDE:Visual Studio 开源库:GitHub.SharpDx 入门示例:SharpDX_D3D12HelloWorld 为什么选择 SharpDx? SharpDx 库与 UWP 兼 ...
- Js基础---红宝书读书日记(1)-------基本类型和引用类型
JS的变量可能包含两种不同数据类型的值,基本类型和引用类型; 基本类型是指简单的数据段,引用类型是指可能由多个值构成的对象; JS高级程序设计第三章介绍了变量分为 5种简单数据类型(string/nu ...
- Redis Cluster日常操作命令梳理
在之前的一篇文章已经介绍了Redis Cluster及其部署,下面说下Redis Cluster日常操作命令: 一.以下命令是Redis Cluster集群所独有的,执行下面命令需要先登录redis: ...
- CMake系列之三:多个源文件-同一目录
同一目录,多个源文件 把前面的main.c里面的power函数单独写入到一个MathFunctions.c源文件里,目录下的文件结构如下: ./Demo2 | +--- main.c | +--- M ...
- Flask-论坛开发-3-数据库
对Flask感兴趣的,可以看下这个视频教程:http://study.163.com/course/courseLearn.htm?courseId=1004091002 1. SQLAlchemy ...
- 在VS2017上对C++项目进行单元测试
操作系统:win10 VS2017安装:http://www.cnblogs.com/Metak/p/7471671.html 参考博客: http://blog.csdn.net/lovehaiho ...
- 腾讯 xtestserver 基本使用教程~
刚刚简单录制了下 腾讯demo的基本测试脚本 成功~get新技能成功~开心ing~ 体验就是: 1.各种安卓机找开发者中心选项的usb调试模式太难找了.. 2.不管录制还是播放录制时都感觉好慢... ...