1.如何利用反射的机制得到泛型的类型的理解: 注意反射时候 新建的对象的属性名 与反射时候的反射字符串必须保持一致
1 package com.tetsReflection; 2 3 /**JDBC 查询得到属性字段 反射机制返回到 JavaBean中相同类属性名的对象中 4 * */ 5 import java.lang.reflect.*; 6 public class ReflectionUtils { 7 8 /** 9 * 使 filed 变为可访问 10 * @param field 11 */ 12 public static void makeAccessible(Field field){ 13 if(!Modifier.isPublic(field.getModifiers())){ 14 field.setAccessible(true); 15 } 16 } 17 /** 18 * 直接设置对象的属性,忽略 private/protected 修饰符, 也不经过 setter 19 * @param object 20 * @param fieldName 属性名称 21 * @param value*/ 22 public static void setFieldValue(Object object, String fieldName, Object value){ 23 24 Field field=getDeclaredField(object,fieldName); 25 if(field==null) 26 throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]"); 27 28 // 让 private 元素变得可以访问,field.setAccessible(); 29 makeAccessible(field); 30 31 try { 32 field.set(object, value); 33 } catch (IllegalArgumentException | IllegalAccessException e) { 34 // TODO Auto-generated catch block 35 e.printStackTrace(); 36 } 37 } 38 39 /** 40 * 循环向上转型, 获取对象的 DeclaredField 41 * @param object 42 * @param filedName 43 * @return 44 */ 45 public static Field getDeclaredField(Object object, String filedName) 46 { 47 // 一步步的循环得到 获取声明对象的祖宗类 48 for(Class<?> superClass=object.getClass() ; superClass!=Object.class;superClass=superClass.getSuperclass()) 49 { 50 try { 51 return superClass.getDeclaredField(filedName); 52 } catch (NoSuchFieldException | SecurityException e) { 53 // TODO Auto-generated catch block 54 e.printStackTrace(); 55 } 56 } 57 return null; 58 } 59 60 /** 61 * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter 62 * @param object 63 * @param fieldName 64 * @return 65 */ 66 public static Object getFieldValue(Object object, String fieldName){ 67 Field field=getDeclaredField(object,fieldName); 68 69 if (field == null) 70 throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]"); 71 72 makeAccessible(field); 73 Object result=null; 74 75 try { 76 result=field.get(object); 77 } catch (IllegalArgumentException | IllegalAccessException e) { 78 // TODO Auto-generated catch block 79 e.printStackTrace(); 80 } 81 return result; 82 } 83 /** 84 * 循环向上转型, 获取对象的 DeclaredMethod 85 * @param object 86 * @param methodName 87 * @param parameterTypes: 指定特定成员方法有重载可能性,必须指定特定的类型变量 88 * @return 89 */ 90 public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) 91 { 92 for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){ 93 try { 94 //superClass.getMethod(methodName, parameterTypes); 95 return superClass.getDeclaredMethod(methodName, parameterTypes); 96 } catch (NoSuchMethodException e) { 97 //Method 不在当前类定义, 继续向上转型 98 } 99 //.. 100 } 101 102 return null; 103 } 104 /** 105 * 直接调用对象方法, 而忽略修饰符(private, protected) 106 * @param object 107 * @param methodName 108 * @param parameterTypes 109 * @param parameters 110 * @return 111 * @throws InvocationTargetException 112 * @throws IllegalArgumentException 113 */ 114 public static Object invokeMethod(Object object, String methodName, Class<?> [] parameterTypes, 115 Object [] parameters) throws InvocationTargetException{ 116 Method method=getDeclaredMethod(object,methodName, parameterTypes); 117 118 if(method==null) 119 throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]"); 120 method.setAccessible(true); 121 122 // 使用 method.invoke()方法进行运行 123 try { 124 method.invoke(object, parameters); 125 } catch (IllegalAccessException | IllegalArgumentException e) { 126 // TODO Auto-generated catch block 127 e.printStackTrace(); 128 } 129 return method; 130 } 131 132 /** 133 * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型 134 * 如: public EmployeeDao extends BaseDao<Employee, String> 135 * @param clazz 136 * @param index 137 * @return 138 */ 139 public static Class getSuperClassGenricType(Class clazz,int index) 140 { 141 Type genType=clazz.getGenericSuperclass(); 142 143 // 判定s是否是ParameterType相对应的 144 if(!(genType instanceof ParameterizedType) ) 145 return Object.class; 146 147 // 强制转换 获取超类泛型参数实际类型,返回genType 是类的接口,基本类型或者void 148 Type []params=((ParameterizedType)genType).getActualTypeArguments(); 149 150 if(index>=params.length || index<0) 151 return Object.class; 152 153 if(!(params[index] instanceof Class)) 154 return Object.class; 155 return (Class) params[index]; 156 } 157 }
2.
1 package com.atguigu.mvcapp; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.ResultSetMetaData; 7 import java.util.HashMap; 8 import java.util.Map; 9 10 import org.junit.Test; 11 12 public class JDBCTest { 13 14 @Test 15 public void testGet() 16 { 17 String sql=null; 18 sql="select id studentid,username studentname,address studentaddress,phone studentphone from EMP where id=?"; 19 20 Student student=get(Student.class,sql,2); 21 System.out.println(student); 22 23 } 24 public <T> T get(Class <T>clazz,String sql,Object...args) 25 { 26 // 不清楚对象是什么 27 T entiry=null; 28 Connection conn=null; 29 PreparedStatement ps=null; 30 ResultSet rs=null; 31 32 try { 33 conn=JDBCUtils.getMysqlConn(); 34 35 ps=conn.prepareStatement(sql); 36 37 for(int i=0;i<args.length;i++) 38 { 39 ps.setObject(i+1,args[i]); 40 41 } 42 rs=ps.executeQuery(); 43 44 // 将 rs 的属性存储到Map 对象 45 Map<String,Object> map=new HashMap<String,Object>(); 46 47 while(rs.next()) 48 { 49 entiry= clazz.newInstance(); 50 51 // 不清楚从SQL 返回几个字段 采用SQL语句解析选择哪些列 52 // 得到对哪些属性进行赋值 53 54 // 1. 得到SQLMetaData columnname;数据库别名与类的属性对应 55 ResultSetMetaData rsmd=rs.getMetaData(); 56 57 int countCoumn=rsmd.getColumnCount(); 58 // 每一条记录就是一个对象,rs.next()多条记录就有多个对象 59 for(int i=0;i<countCoumn;i++) 60 { 61 String columnLabel=rsmd.getColumnLabel(i+1); 62 Object columnValue=rs.getObject(i+1); 63 map.put(columnLabel, columnValue); 64 } 65 } 66 // 利用反射机制进行 创建新的对象 67 if(!map.isEmpty()) 68 { 69 70 for(Map.Entry<String, Object> entiry1:map.entrySet()) 71 { 72 String property=entiry1.getKey(); 73 Object value=entiry1.getValue(); 74 // c测试打印一下 75 System.out.println(property +": "+value); 76 // 注意 反射时 属性名反射的value 保持一致 77 ReflectionUtils.setFieldValue(entiry,property, value); 78 } 79 } 80 81 82 } catch (Exception e) { 83 // TODO Auto-generated catch block 84 e.printStackTrace(); 85 } 86 finally{ 87 JDBCUtils.closeMysql(rs, ps, conn); 88 } 89 return entiry; 90 91 92 93 } 94 }
3. getClass()--这是一个非静态的方法得到Class clazz---
问题一:反射过程中 如果不知道 原先类,怎么样去确定clazz=***.class
由于 反射条件中Class clazz=Person.class,写DAO中事先不清楚clazz属于什么类型的.clazz ,下面的构造器中 初始化过程中 确定 clazz=***.class
知识:
我们一般使用对象简介的继承Object类,在Object类中包含一个 getClass的方法,利用这个方法获取一个实体的类型类,类型类 表示这个实体属于哪个类, 同时所有的类型类都是 Class类的实体, getClass()获取本子类属于的类型
1 Type surperclass= getClass().getGenericSuperclass(); 2 //// getClass() 表示本子类,得到父类的泛型 3 if(surperclass instanceof ParameterizedType) 4 { 5 ParameterizedType param=(ParameterizedType)surperclass; 6 Type[] typeargs=param.getActualTypeArguments(); 7 8 if(typeargs!=null && typeargs.length>0 ) 9 { 10 if(typeargs[0] instanceof Class) 11 this.clazz=(Class<T>) typeargs[0]; 12 } 13 }