java泛型反射总结

引入:

      在需求中,数据库有两张表user,admin。我们要查询里面的id,name等信息通常都是写两个dao,然后分别给每个查询字段写一套方法。

     然而其实查询这些字段的方法都大同小异,所以产生了一个更好的解决办法,就是写一个通用的dao,然后把相同的方法写在通用的dao(genericDao)里,然后然实体dao去继     承它。

   

    下面通过模拟 贴出一般做法 和 优化后的做法:

    首先 在数据库里建好两张表,分别为user和admin,再插入一些数据

   

CREATE TABLE USER(
	id INT PRIMARY KEY,
	userName VARCHAR(20),
	age INT
	);
CREATE TABLE admin(
	id INT PRIMARY KEY,
	adminName VARCHAR(20),
	status_ INT
	);
	
INSERT INTO USER VALUES(1,'李四',21);
INSERT INTO USER VALUES(2,'张三',20);

INSERT INTO admin VALUES(1,'超级管理员',1);
INSERT INTO admin VALUES(2,'普通管理员',0);
        截下来写两个实体类

public class admin {
	private int id;
	private String adminName;
	private int status_;
	public admin() {
		super();
		// TODO Auto-generated constructor stub
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getAdminName() {
		return adminName;
	}
	public void setAdminName(String adminName) {
		this.adminName = adminName;
	}
	public int getStatus_() {
		return status_;
	}
	public void setStatus_(int status_) {
		this.status_ = status_;
	}
	@Override
	public String toString() {
		return "admin [id=" + id + ", adminName=" + adminName + ", status_=" + status_ + "]";
	}
	
}

public class user {
	private int id;
	private String userName;
	private int age;
	public user() {
		super();
		// TODO Auto-generated constructor stub
	}
	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;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "userDao [id=" + id + ", userName=" + userName + ", age=" + age + "]";
	}
	
}

一般做法

   
public class adminDao{
	
	public admin getById(int id)
	{
		QueryRunner qr=jdbcUtil.getQueryRunner();
		try {
			return (admin)qr.query("select * from admin where id=", new BeanHandler(admin.class),new Object[]{id});
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	@Test
	public void testId()
	{
		adminDao adminDao = new adminDao();
		admin byId = adminDao.getById(2);
		System.out.println(byId);
	}
}

public class userDao extends genericDao<user>{
	public user getById(int id)
	{
		QueryRunner qr=jdbcUtil.getQueryRunner();
		try {
			return (user)qr.query("select * from user where id=?", new BeanHandler(user.class),new Object[]{id});
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	@Test
	public void testId()
	{
		userDao userDao = new userDao();
		user byId = userDao.getById(2);
		System.out.println(byId);
	}
	
}

利用泛型优化后的做法:

    首先写一个genericDao
  
**
 * 通用的dao方法
 * @author Administrator
 *
 */
public class genericDao <T>{
	private Class clazz;
	private String tableName;
	
	public genericDao(Class clazz,String tableName)
	{
		this.clazz=clazz;
		this.tableName=tableName;
	}
	public  T getById(int id)
	{
		QueryRunner qr=jdbcUtil.getQueryRunner();
		try {
			return (T)qr.query("select * from "+tableName+" where id=?", new BeanHandler(clazz),new Object[]{id});
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}
然后让实体Dao类分别继承它
public class adminDao extends genericDao<admin>{	
	public adminDao() {
		super(admin.class, "admin");
	}

	@Test
	public void testId()
	{
		adminDao adminDao = new adminDao();
		admin byId = adminDao.getById(2);
		System.out.println(byId);
	}
}

public class userDao extends genericDao<user>{

	public userDao() {
		super(user.class, "user");
	}

	@Test
	public void testId()
	{
		userDao userDao = new userDao();
		user byId = userDao.getById(2);
		System.out.println(byId);
	}
	
}



利用泛型反射技术优化后的做法


generic类
/**
 * 通用的dao方法
 * @author Administrator
 *
 */
public class genericDao <T>{
	private Class clazz;
	private String tableName;
	
	public genericDao()
	{
		System.out.println(this);//this 指当前运行的类对象  如果有子类继承它,则它指的是子类,而不是generic本身类
		System.out.println(this.getClass());//获得当前运行类的字节码
		System.out.println(this.getClass().getSimpleName());//获得当前运行类的类名
		System.out.println(this.getClass().getSuperclass());//获得当前运行类的父类的字节码
		System.out.println(this.getClass().getGenericSuperclass());//获得参数化类型  reflect.genericDao<reflect.admin>
		/**
		 * 参数化类型:genericDao<reflect.admin>
		 * 实体类型:reflect.admin
		 */
		//1.先获得当前运行类的泛型父类类型
		Type type = this.getClass().getGenericSuperclass();
		//2.强转为参数化类型
		ParameterizedType p=(ParameterizedType)type;
		//3.获取参数化类型中,实际类型的定义
		Type[] actualTypeArguments = p.getActualTypeArguments();
		//获取数组的第一个元素,即我们想要的实际类型的字节码类型
		clazz=(Class<T>) actualTypeArguments[0];
		
		//给表名赋值
		tableName=clazz.getSimpleName();
		
	}
	public  T getById(int id)
	{
		QueryRunner qr=jdbcUtil.getQueryRunner();
		try {
			return (T)qr.query("select * from "+tableName+" where id=?", new BeanHandler(clazz),new Object[]{id});
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}

 简化后的dao类
public class userDao extends genericDao<user>{

	@Test
	public void testId()
	{
		userDao userDao = new userDao();
		user byId = userDao.getById(2);
		System.out.println(byId);
	}
	
}
public class adminDao extends genericDao<admin>{
	

	@Test
	public void testId()
	{
		adminDao adminDao = new adminDao();
		admin byId = adminDao.getById(2);
		System.out.println(byId);
	}
}


得出结论:子类继承父类,并传一个实际类型给父类,父类可以在类中通过反射技术先获得参数化类型,再获得参数化类型中的实际类型。即xxx.class

     

原文地址:https://www.cnblogs.com/chenny3/p/10226229.html