java反射機制(轉載)

1、什麼是反射機制
        簡單的來講,反射機制指的是程序在運行時可以獲取自身的信息。在java中,只要給定類的名字,
    那麼就能夠經過反射機制來得到類的全部信息。
2、哪裏用到反射機制
        有些時候,咱們用過一些知識,可是並不知道它的專業術語是什麼,在剛剛學jdbc時用過一行代碼,
    Class.forName("com.mysql.jdbc.Driver.class").newInstance();可是那時候只知道那行代碼是生成
    驅動對象實例,並不知道它的具體含義。聽了反射機制這節課後,才知道,原來這就是反射,如今不少開
    框架都用到反射機制,hibernate、struts都是用反射機制實現的。
3、反射機制的優勢與缺點
        爲何要用反射機制?直接建立對象不就能夠了嗎,這就涉及到了動態與靜態的概念,
    靜態編譯:在編譯時肯定類型,綁定對象,即經過。
    動態編譯:運行時肯定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多
    態的應用,有以下降類之間的藕合性。
    一句話,反射機制的優勢就是能夠實現動態建立對象和編譯,體現出很大的靈活性,特別是在J2EE的開發中
    它的靈活性就表現的十分明顯。好比,一個大型的軟件,不可能一次就把把它設計的很完美,當這個程序編
    譯後,發佈了,當發現須要更新某些功能時,咱們不可能要用戶把之前的卸載,再從新安裝新的版本,假如
    這樣的話,這個軟件確定是沒有多少人用的。採用靜態的話,須要把整個程序從新編譯一次才能夠實現功能
    的更新,而採用反射機制的話,它就能夠不用卸載,只須要在運行時才動態的建立和編譯,就能夠實現該功
    能。
       它的缺點是對性能有影響。使用反射基本上是一種解釋操做,咱們能夠告訴JVM,咱們但願作什麼而且它
    知足咱們的要求。這類操做老是慢於只直接執行相同的操做。
4、利用反射機制能得到什麼信息
         一句話,類中有什麼信息,它就能夠得到什麼信息,不過前提是得知道類的名字,要不就沒有後文了
    首先得根據傳入的類的全名來建立Class對象。
    Class c=Class.forName("className");註明:className必須爲全名,也就是得包含包名,好比,cn.netjava.pojo.UserInfo;
    Object obj=c.newInstance();//建立對象的實例
    OK,有了對象就什麼都好辦了,想要什麼信息就有什麼信息了。  
    得到構造函數的方法
    Constructor getConstructor(Class[] params)//根據指定參數得到public構造器
java

    Constructor[] getConstructors()//得到public的全部構造器mysql

    Constructor getDeclaredConstructor(Class[] params)//根據指定參數得到public和非public的構造器程序員

    Constructor[] getDeclaredConstructors()//得到public的全部構造器
   
    得到類方法的方法
    Method getMethod(String name, Class[] params),根據方法名,參數類型得到方法sql

    Method[] getMethods()//得到全部的public方法數據庫

    Method getDeclaredMethod(String name, Class[] params)//根據方法名和參數類型,得到public和非public的方法數組

    Method[] getDeclaredMethods()//得到因此的public和非public方法
   
    得到類中屬性的方法
    Field getField(String name)//根據變量名獲得相應的public變量session

    Field[] getFields()//得到類中因此public的方法框架

    Field getDeclaredField(String name)//根據方法名得到public和非public變量ide

    Field[] getDeclaredFields()//得到類中全部的public和非public方法
    經常使用的就這些,知道這些,其餘的都好辦……
5、用反射機制能幹什麼事
        剛開始在使用jdbc時侯,在編寫訪問數據庫時寫到想吐,有八個表,每一個表都有增刪改查中操做
    那時候還不知道有反射機制這個概念,因此就對不一樣的表建立不一樣的dao類,這樣不只開發速率地,並且代碼
    冗餘的厲害,最要命的是看着差很少的,而後直接複製修改,因爲容易犯各類低級的錯誤(大小寫啊,多一
    個或少一個字母啊……),一個錯誤就可讓你找半天。
        有了java反射機制,什麼都好辦了,只須要寫一個dao類,四個方法,增刪改查,傳入不一樣的對象,就OK啦,
    無需爲每個表都建立dao類,反射機制會自動幫咱們完成剩下的事情,這就是它的好處。說白了,反射機制就是專門
    幫咱們作那些重複的有規則的事情,因此如今不少的自動生成代碼的軟件就是運用反射機制來完成的,只要你按照規則
    輸入相關的參數,因此低級的程序員慢慢的就被抹殺了,爲何?由於代碼都不用寫了,隨便一我的都會開發,還要程
    序員幹什麼啊?因此咱們只有一條出路,那就是努力努力再努力,成爲高級程序員,專門開發傻瓜軟件,讓其餘程序員  到 一邊涼快去,呵呵~
6、用反射機制實現對數據庫數據的增、查例子
    基本原理;保存數據時,把須要保存的對象的屬性值所有取出來再拼湊sql語句
                 查詢時,將查詢到的數據所有包裝成一個java對象。
    遊戲規則:俗話說的好,無規矩不成方圓,特別是程序來講,它只能作有規則的事情,沒有規則的它幹不了,好,那就
              先定規則
              1)數據庫的每個表對象一個pojo類,表中的每個字段對應pojo類的中的一個屬性。
                 而且pojo類的名字和表的名字相同,屬性名和字段名相同,大小寫沒有關係,由於數據庫通常不區分大小寫 
              2)爲pojo類中的每個屬性添加標準的set和get方法。
    有了遊戲規則,那麼開始遊戲吧。
函數

       2)爲pojo類中的每個屬性添加標準的set和get方法。
    有了遊戲規則,那麼開始遊戲吧。

   一、首先數據庫的有一個表,假設數據庫名稱爲:blogsystem,裏面的一個表名userinfo。如圖:

 

          
   二、建立對應的pojo類:

 

 

 

Java代碼   收藏代碼
  1. package cn.netjava.pojo;  
  2.   
  3. public class UserInfo {  
  4. private int id;  
  5. private String name;  
  6. private String pwd;  
  7. private int age;  
  8.   
  9. @Override  
  10. public String toString() {  
  11.     return "UserInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + ", age="  
  12.             + age + "]";  
  13. }  
  14. public int getId() {  
  15.     return id;  
  16. }  
  17. public void setId(int id) {  
  18.     this.id = id;  
  19. }  
  20. public String getName() {  
  21.     return name;  
  22. }  
  23. public void setName(String name) {  
  24.     this.name = name;  
  25. }  
  26. public String getPwd() {  
  27.     return pwd;  
  28. }  
  29. public void setPwd(String pwd) {  
  30.     this.pwd = pwd;  
  31. }  
  32. public int getAge() {  
  33.     return age;  
  34. }  
  35. public void setAge(int age) {  
  36.     this.age = age;  
  37. }  
  38.   
  39. }  

 

 

 

二、編寫得到數據庫鏈接的工廠類:

 

Java代碼   收藏代碼
  1. package cn.netjava.factory;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DriverManager;  
  5.   
  6. public class Connect2DBFactory {  
  7.     public static Connection getDBConnection() {  
  8.         Connection conn = null;  
  9.         try {  
  10.             Class.forName("com.mysql.jdbc.Driver");  
  11.             String url = "jdbc:mysql://localhost:3306/blogsystem";  
  12.             String user = "root";  
  13.             String password = "netjava";  
  14.             conn = DriverManager.getConnection(url, user, password);  
  15.         } catch (Exception e) {  
  16.             e.printStackTrace();  
  17.         }  
  18.   
  19.         return conn;  
  20.     }  
  21. }  

 

 三、好戲開始啦,編寫操做數據庫的dao類

 

Java代碼   收藏代碼
  1. package cn.netjava.session;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5. import java.sql.Connection;  
  6. import java.sql.PreparedStatement;  
  7. import java.sql.ResultSet;  
  8. import java.sql.SQLException;  
  9. import java.sql.Statement;  
  10. import java.util.ArrayList;  
  11. import java.util.List;  
  12.   
  13. import cn.netjava.factory.Connect2DBFactory;  
  14. import cn.netjava.pojo.UserInfo;  
  15.   
  16. public class NetJavaSession {  
  17.     /** 
  18.      * 解析出保存對象的sql語句 
  19.      *  
  20.      * @param object 
  21.      *            :須要保存的對象 
  22.      * @return:保存對象的sql語句 
  23.      */  
  24.     public static String getSaveObjectSql(Object object) {  
  25.         // 定義一個sql字符串  
  26.         String sql = "insert into ";  
  27.         // 獲得對象的類  
  28.         Class c = object.getClass();  
  29.         // 獲得對象中全部的方法  
  30.         Method[] methods = c.getMethods();  
  31.         // 獲得對象中全部的屬性  
  32.         Field[] fields = c.getFields();  
  33.         // 獲得對象類的名字  
  34.         String cName = c.getName();  
  35.         // 從類的名字中解析出表名  
  36.         String tableName = cName.substring(cName.lastIndexOf(".") + 1,  
  37.                 cName.length());  
  38.         sql += tableName + "(";  
  39.         List<String> mList = new ArrayList<String>();  
  40.         List vList = new ArrayList();  
  41.         for (Method method : methods) {  
  42.             String mName = method.getName();  
  43.             if (mName.startsWith("get") && !mName.startsWith("getClass")) {  
  44.                 String fieldName = mName.substring(3, mName.length());  
  45.                 mList.add(fieldName);  
  46.                 System.out.println("字段名字----->" + fieldName);  
  47.                 try {  
  48.                     Object value = method.invoke(object, null);  
  49.                     System.out.println("執行方法返回的值:" + value);  
  50.                     if (value instanceof String) {  
  51.                         vList.add("\"" + value + "\"");  
  52.                         System.out.println("字段值------>" + value);  
  53.                     } else {  
  54.                         vList.add(value);  
  55.                     }  
  56.                 } catch (Exception e) {  
  57.                     e.printStackTrace();  
  58.                 }  
  59.             }  
  60.         }  
  61.         for (int i = 0; i < mList.size(); i++) {  
  62.             if (i < mList.size() - 1) {  
  63.                 sql += mList.get(i) + ",";  
  64.             } else {  
  65.                 sql += mList.get(i) + ") values(";  
  66.             }  
  67.         }  
  68.         for (int i = 0; i < vList.size(); i++) {  
  69.             if (i < vList.size() - 1) {  
  70.                 sql += vList.get(i) + ",";  
  71.             } else {  
  72.                 sql += vList.get(i) + ")";  
  73.             }  
  74.         }  
  75.   
  76.         return sql;  
  77.     }  
  78.   
  79.     public static List getDatasFromDB(String tableName, int Id) {  
  80.   
  81.         return null;  
  82.   
  83.     }  
  84.   
  85.     /** 
  86.      * 將對象保存到數據庫中 
  87.      *  
  88.      * @param object 
  89.      *            :須要保存的對象 
  90.      * @return:方法執行的結果;1:表示成功,0:表示失敗 
  91.      */  
  92.     public int saveObject(Object object) {  
  93.         Connection con = Connect2DBFactory.getDBConnection();  
  94.         String sql = getSaveObjectSql(object);  
  95.         try {  
  96.             // Statement statement=(Statement) con.createStatement();  
  97.             PreparedStatement psmt = con.prepareStatement(sql);  
  98.             psmt.executeUpdate();  
  99.             return 1;  
  100.         } catch (SQLException e) {  
  101.             e.printStackTrace();  
  102.             return 0;  
  103.         }  
  104.     }  
  105.   
  106.     /** 
  107.      * 從數據庫中取得對象 
  108.      *  
  109.      * @param arg0 
  110.      *            :對象所屬的類 
  111.      * @param id 
  112.      *            :對象的id 
  113.      * @return:須要查找的對象 
  114.      */  
  115.     public Object getObject(String className, int Id) {  
  116.         // 獲得表名字  
  117.         String tableName = className.substring(className.lastIndexOf(".") + 1,  
  118.                 className.length());  
  119.         // 根據類名來建立Class對象  
  120.         Class c = null;  
  121.         try {  
  122.             c = Class.forName(className);  
  123.   
  124.         } catch (ClassNotFoundException e1) {  
  125.   
  126.             e1.printStackTrace();  
  127.         }  
  128.         // 拼湊查詢sql語句  
  129.         String sql = "select * from " + tableName + " where Id=" + Id;  
  130.         System.out.println("查找sql語句:" + sql);  
  131.         // 得到數據庫連接  
  132.         Connection con = Connect2DBFactory.getDBConnection();  
  133.         // 建立類的實例  
  134.         Object obj = null;  
  135.         try {  
  136.   
  137.             Statement stm = con.createStatement();  
  138.             // 獲得執行查尋語句返回的結果集  
  139.             ResultSet set = stm.executeQuery(sql);  
  140.             // 獲得對象的方法數組  
  141.             Method[] methods = c.getMethods();  
  142.             // 遍歷結果集  
  143.             while (set.next()) {  
  144.                 obj = c.newInstance();  
  145.                 // 遍歷對象的方法  
  146.                 for (Method method : methods) {  
  147.                     String methodName = method.getName();  
  148.                     // 若是對象的方法以set開頭  
  149.                     if (methodName.startsWith("set")) {  
  150.                         // 根據方法名字獲得數據表格中字段的名字  
  151.                         String columnName = methodName.substring(3,  
  152.                                 methodName.length());  
  153.                         // 獲得方法的參數類型  
  154.                         Class[] parmts = method.getParameterTypes();  
  155.                         if (parmts[0] == String.class) {  
  156.                             // 若是參數爲String類型,則從結果集中按照列名取得對應的值,而且執行改set方法  
  157.                             method.invoke(obj, set.getString(columnName));  
  158.                         }  
  159.                         if (parmts[0] == int.class) {  
  160.                             method.invoke(obj, set.getInt(columnName));  
  161.                         }  
  162.                     }  
  163.   
  164.                 }  
  165.             }  
  166.   
  167.         } catch (Exception e) {  
  168.             e.printStackTrace();  
  169.         }  
  170.         return obj;  
  171.     }  
  172. }  

 

 

 

 四、開始測試效果怎麼樣:

 

Java代碼   收藏代碼
  1. package cn.netjava.tester;  
  2.   
  3. import cn.netjava.pojo.UserInfo;  
  4. import cn.netjava.session.NetJavaSession;  
  5.   
  6. public class Tester {  
  7.     public static void main(String args[]) {  
  8.         //得到NetJavaSession對象  
  9.         NetJavaSession session = new NetJavaSession();  
  10.         //建立一個UserInfo對象  
  11.         UserInfo user = new UserInfo();  
  12.         //設置對象的屬性  
  13.         user.setId(6988);  
  14.         user.setAge(44);  
  15.         user.setPwd("pwd");  
  16.         user.setName("champion");  
  17.         //將對象保存到數據庫中  
  18.         String sql = session.getSaveObjectSql(user);  
  19.         System.out.println("保存對象的sql語句:" + sql);  
  20.         //查找對象  
  21.         UserInfo userInfo = (UserInfo) session.getObject(  
  22.                 "cn.netjava.pojo.UserInfo", 6988);  
  23.         System.out.println("獲取到的信息:" + userInfo);  
  24.   
  25.     }  
  26. }  

 

 

 

五、打印出來的結果:

 

       

 

7、總節一下

 

      總的來講,java反射機制是一個很好用的東西,用它能夠解決不少死的東西,由於反射機制的靈活行很大,有了他,咱們就不要花太多的時間來寫操作數據庫的 代碼了,而是方法更多的時間在項目的邏輯功能上,這個能夠很大的減小開發時間,並且代碼的可讀性好。先在的不少開源框架都是才用的反射機制,它只要配置文 件,而後按規則來調用他的方法就能夠了。

 

 

 

轉載地址:http://champion-netjava-163-com.iteye.com/blog/982080

相關文章
相關標籤/搜索