泛型的反射 案例,设置通用方法,会用到反射泛型!
步骤: 1. 案例分析 / 实现 2. 涉及知识点(jdk api) 3. 优化 / 反射泛型
反射泛型涉及API: Student 类型的表示 Id name ParameterizedType 参数化类型的表示 ArrayList<String>();
Type 接口,任何类型默认的接口! 包括: 引用类型、原始类型、参数化类型
List<String> list = new ArrayList<String>(); 泛型集合: list 集合元素定义:new ArrayList<String>(); 中的String 参数化类型: ParameterizedType 即:“ArrayList<String> ” 为参数化类型
反射泛型案例 public class AdminDao extends BaseDao<Admin> {} public class AccountDao extends BaseDao<Account> {}
/**
- 所有dao的公用的方法,都在这里实现
- @author Jie.Yuan
*/ public class BaseDao<T>{
// 保存当前运行类的参数化类型中的实际的类型
private Class clazz;
// 表名
private String tableName;
// 构造函数: 1. 获取当前运行类的参数化类型; 2. 获取参数化类型中实际类型的定义(class)
public BaseDao(){
// this 表示当前运行类 (AccountDao/AdminDao)
// this.getClass() 当前运行类的字节码(AccountDao.class/AdminDao.class)
// this.getClass().getGenericSuperclass(); 当前运行类的父类,即为BaseDao<Account>
// 其实就是“参数化类型”, ParameterizedType
Type type = this.getClass().getGenericSuperclass();
// 强制转换为“参数化类型” 【BaseDao<Account>】
ParameterizedType pt = (ParameterizedType) type;
// 获取参数化类型中,实际类型的定义 【new Type[]{Account.class}】
Type types[] = pt.getActualTypeArguments();
// 获取数据的第一个元素:Accout.class
clazz = (Class) types[0];
// 表名 (与类名一样,只要获取类名就可以)
tableName = clazz.getSimpleName();
}
/**
* 主键查询
* @param id 主键值
* @return 返回封装后的对象
*/
public T findById(int id){
/*
* 1. 知道封装的对象的类型
* 2. 表名【表名与对象名称一样, 且主键都为id】
*
* 即,
* ---》得到当前运行类继承的父类 BaseDao<Account>
* ----》 得到Account.class
*/
String sql = "select * from " + tableName + " where id=? ";
try {
return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 查询全部
* @return
*/
public List<T> getAll(){
String sql = "select * from " + tableName ;
try {
return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
- 反射复习 反射,可以在运行时期动态创建对象;获取对象的属性、方法;
public class Admin {
// Field
private int id = 1000;
private String name = "匿名";
// Constructor
public Admin(){
System.out.println("Admin.Admin()");
}
public Admin(String name){
System.out.println("Admin.Admin()" + name);
}
// Method
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;
}
}
// 反射技术 public class App {
// 1. 创建对象
@Test
public void testInfo() throws Exception {
// 类全名
String className = "cn.andday.c_reflect.Admin";
// 得到类字节码
Class<?> clazz = Class.forName(className);
// 创建对象1: 默认构造函数简写
//Admin admin = (Admin) clazz.newInstance();
// 创建对象2: 通过带参数构造器创建对象
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
Admin admin = (Admin) constructor.newInstance("Jack");
}
@Test
//2. 获取属性名称、值
public void testField() throws Exception {
// 类全名
String className = "cn.andday.c_reflect.Admin";
// 得到类字节码
Class<?> clazz = Class.forName(className);
// 对象
Admin admin = (Admin) clazz.newInstance();
// 获取所有的属性名称
Field[] fs = clazz.getDeclaredFields();
// 遍历:输出每一个属性名称、值
for (Field f : fs) {
// 设置强制访问
f.setAccessible(true);
// 名称
String name = f.getName();
// 值
Object value = f.get(admin);
System.out.println(name + value);
}
}
@Test
//3. 反射获取方法
public void testMethod() throws Exception {
// 类全名
String className = "cn.andday.c_reflect.Admin";
// 得到类字节码
Class<?> clazz = Class.forName(className);
// 对象
Admin admin = (Admin) clazz.newInstance();
// 获取方法对象 public int getId() {
Method m = clazz.getDeclaredMethod("getId");
// 调用方法
Object r_value = m.invoke(admin);
System.out.println(r_value);
}