有时候我们需要知道当前类所传入的泛型的具体类型而进行下一步操作,这是我们可以使用泛型反射。
1.假如Dao层的接口有很多共同的方法,增删改查,我们可以对他进行提取到一个公共接口IBaseDao<T>
package com.sg.xjgc.generic_reflect;
import java.util.List;
/**
* @date on 15:31 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description Dao层顶级抽取接口
*/
public interface IBaseDao<T> {
/**
* 根据主键查询
* @param id 实体类id
* @return T
*/
T findById(int id);
/**
* 查询所有
* @return List<T>
*/
List<T> findAll();
/**
* 修改
* @param p 实体类对象
*/
void update(T p);
/**
* 删除
* @param p 实体类对象
*/
void delete(T p);
/**
* 添加
* @param p 实体类对象
*/
void add(T p);
}
2.创建它的实现类BaseDaoImpl,通过在构造函数中通过泛型反射获取当前类传入的泛型T具体类型。
package com.sg.xjgc.generic_reflect;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
/**
* @date on 15:37 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description IBaseDao的实现类
*/
public class BaseDaoImpl<T> implements IBaseDao<T>{
private Class clazz;
/**
* 在这里通过泛型反射得到具体的泛型类Class对象
*/
public BaseDaoImpl(){
//这里this代表的是BaseDaoImpl的子类对象
//得到当当前类(父类)上的泛型T--父类型
Type type = this.getClass().getGenericSuperclass();
//得到当前类上所有的泛型类型Class
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
//得到具体传入的泛型类Class对象
clazz = (Class) types[0];
}
/**
* 根据主键查询
* @param id 实体类id
* @return T
*/
@Override
public T findById(int id) {
System.out.println(clazz);
return null;
}
/**
* 查询所有
*
* @return List<T>
*/
@Override
public List<T> findAll() {
System.out.println(clazz);
return null;
}
/**
* 修改
*
* @param p 实体类对象
*/
@Override
public void update(T p) {
System.out.println(clazz);
}
/**
* 删除
*
* @param p 实体类对象
*/
@Override
public void delete(T p) {
System.out.println(clazz);
}
/**
* 添加
*
* @param p 实体类对象
*/
@Override
public void add(T p) {
System.out.println(clazz);
}
}
3.分别创建实体类User和Product测试使用。
package com.sg.xjgc.generic_reflect;
/**
* @date on 15:46 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description 模拟用户实体类
*/
public class User {
private int id;
private String userName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
package com.sg.xjgc.generic_reflect;
/**
* @date on 15:47 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description 模拟产品实体类
*/
public class Product {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4.分别创建针对User业务和Product业务的Dao层具体实现类继承BaseDaoImpl<T>,因为公共方法已经被父类实现,因此它什么也不用做,传入具体泛型即可。
package com.sg.xjgc.generic_reflect;
/**
* @date on 15:49 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description 具体用户dao
*/
public class UserDaoImpl extends BaseDaoImpl<User> {
//子类什么都不用做
}
package com.sg.xjgc.generic_reflect;
/**
* @date on 15:49 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description 具体产品dao
*/
public class ProductDaoImpl extends BaseDaoImpl<Product>{
//子类什么都不用做
}
5.编写测试类,来查看能否获得泛型类的具体类型。
package com.sg.xjgc.generic_reflect;
/**
* @date on 15:51 2018/12/21
* @package com.sg.xjgc.generic_reflect
* @description 测试
*/
public class Test {
@org.junit.Test
public void testUserDaoImpl(){
IBaseDao baseDao = new UserDaoImpl();
baseDao.findAll();
//结果:class com.sg.xjgc.generic_reflect.User
}
@org.junit.Test
public void testProductDaoImpl(){
IBaseDao baseDao = new ProductDaoImpl();
baseDao.findAll();
//结果:class com.sg.xjgc.generic_reflect.Product
}
}