反射泛型的使用

  Type是java.lang.reflect包下的一个接口,该接口代表所有类型的公共接口,Class是Type接口的实现类。

java采用泛型擦除的机制来引入泛型,也就是说,泛型仅仅是给编译器javac看的,来确保数据的安全性和免去数据类型转换,但是,一旦编译完成,所有和泛型相关的东西都被擦除,这一点也可以从类编译的class文件反编译看到。
    在实际应用中,为了获得和泛型有关的信息,Java就新增了几种类型来代表不能被归一到Class类中的类型,但又和基本数据类型齐名的类型,通常使用的是如下两个:
    GenericArrayType: 表示一种元素类型是参数化的类型或者类型变量的数组类型。
    ParameterizedType: 表示一种参数化的类型。

    为什么要引入这两种呢,实际上,在通过反射获取父类或者接口或者成员变量类型等方法中,如果涉及的是泛型的话,就无法获取不到了,所以才引入了上面两种类型。


举例说明整个过程:

Teacher和Student是实体,包含了id,name,age。对实体的操作主要为查询。通过泛型来抽取代码。


import com.jichu.Util.jdbcUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;

public class BaseDao<T> {
    private Class targetClass;
    private String tableName;
    public BaseDao(){
        Class clazz=this.getClass();
        Type type=clazz.getGenericSuperclass();
        ParameterizedType param=(ParameterizedType) type;
        Type[]types=param.getActualTypeArguments();
        Type target=types[0];
        targetClass=(Class) target;
        tableName=targetClass.getSimpleName().toLowerCase();
    }
    public List<T> findAll(){
        QueryRunner qr=new QueryRunner(jdbcUtil.getDs());
        try {
            return (List<T>) qr.query("select *from "+tableName,new BeanListHandler<>(targetClass));
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public T findById(int id) {
        QueryRunner qr=new QueryRunner(jdbcUtil.getDs());
        try {
            return (T)qr.query("select *from "+tableName+" where id=?",new BeanHandler<>(targetClass),new Object[]{id});
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

测试代码:

package com.jichu.generic;

import org.junit.Test;

import java.util.List;

public class TestDao {
    @Test
    public void testStu(){
    StudentDao sdao=new StudentDao();
        System.out.println(sdao.findById(1));
        List<Student>list=sdao.findAll();
        for (Student s:list ) {
            System.out.println(s);
        }
    }
    @Test
    public void testTea(){
        TeacherDao tdao=new TeacherDao();
       // System.out.println(tdao.findById(2));
        List<Teacher>list=tdao.findAll();
        for (Teacher t:list ) {
            System.out.println(t);
        }
    }
}

核心代码如下:

 public BaseDao(){
        1.Class clazz=this.getClass();
        2.Type type=clazz.getGenericSuperclass();
        3.ParameterizedType param=(ParameterizedType) type;
        Type[]types=param.getActualTypeArguments();
        4.Type target=types[0];
        5.targetClass=(Class) target;
        6.tableName=targetClass.getSimpleName().toLowerCase();
    }

第一步获取类对象,class com.jichu.generic.StudentDao

第二步获取当前类对象的父类类型:com.jichu.generic.BaseDao<com.jichu.generic.Student>

第三步把父类类型转换为参数化对象:com.jichu.generic.BaseDao<com.jichu.generic.Student>

第四步获取参数化对象的泛型列表:class com.jichu.generic.Student

第五步把type类型转为class类型

第六步获得最终参数:student
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值