上后谈爱情

导航

 

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      }

 

    

posted on 2017-04-06 15:48  上后谈爱情  阅读(466)  评论(0编辑  收藏  举报