首頁  >  文章  >  Java  >  Java反射機制

Java反射機制

高洛峰
高洛峰原創
2016-12-12 11:36:531232瀏覽

一、什麼是反射機制 
        簡單的來說,反射機制指的是程式在運作時能夠取得自身的資訊。在java中,只要給定類別的名字, 
    那麼就可以透過反射機制來獲得類別的所有資訊。
二、哪裡用到反射機制 
        有些時候,我們用到反射機制 
        有些時候,我們有使用一些知識,但不知道它專業的用語是什麼,剛學過一行程式碼, 
b   Class.forName(jdbc時用過一行程式碼, 
b   Class.forName( .Driver.class").newInstance();但是那時候只知道那行程式碼是產生 
    驅動物件實例,並且不知道它的特定意義。聽了反射機制這堂課後,才知道,原來這就是反射,現在很多開 
    框架都用到反射機制,hibernate、struts都是用反射機制實現的。 
三、反射機制的優點與缺點 
        為什麼使用反射機制?直接創建物件不就可以了嗎,這就涉及到了動態與靜態的概念, 
    靜態編譯:在編譯時確定類型,綁定物件,即通過。 
    動態編譯:執行階段決定類型,綁定物件。動態編譯最大限度地發揮了java的彈性,體現了多 
    態的應用,並有以降低類別之間的藕合性。 
    一句話,反射機制的優點就是可以實現動態創造物件與編譯,體現出極大的彈性,特別是在J2EE的發展中 
    它的彈性表現的十分明顯。例如,一個大型的軟體,不可能一次就把它設計的很完美,當這個程式編 
    譯後,發布了,當發現需要更新某些功能時,我們不可能要用戶把以前的卸載,再重新安裝新的版本,假如 
    這樣的話,這個軟體肯定是沒有多少人用的。採用靜態的話,需要把整個程式重新編譯一次才可以實現功能 
    的更新,而採用反射機制的話,它就可以不用卸載,只需要在運行時才動態的創建和編譯,就可以實現該功 
    能。 
       它的缺點是對效能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什麼並且它 
    滿足我們的要求。這類操作總是慢於只直接執行相同的操作。
四、利用反射機制能獲得什麼信息 
         一句話,類中有什麼信息,它就可以獲得什麼信息,不過前提是得知道類的名字,要不就沒有後文了    類別的全名來建立Class物件。
    Class c=Class.forName("className");註明:className必須為全名,也就是得包含包名,例如,cn.netjava.pojo.UserInfo; 
    Object obj=c.newInstance();/ /建立物件的實例 
    OK,有了物件就什麼都好辦了,想要什麼資訊就有什麼資訊了。
    取得建構子的方法 

    Constructor getConstructor(Class[] params)//根據指定參數取得public建構器

    Constructor[] //依照指定參數取得public和非public的建構子

    Constructor[] getDeclaredConstructors()//取得public的所有建構子 

    取得類別方法的方法 
  
    取得類別方法的方法 

  名,參數型別取得方法

    Method[] getMethods()//取得所有的public方法

    Method getDeclaredMethod(String name, Class[] params)//依照方法名稱和參數型,取得publiclaredMethod(String name, Class[]params)//根據方法名稱和參數型,取得public和非public

    Method[] getDeclaredMethods()//取得所以的public和非public方法 
    取得類別中屬性的方法 
    Field getField(String name)//根據變數名稱中取得對應的變數名稱/取得類別中所以public的方法

    Field getDeclaredField(String name)//依方法名稱取得public和非public變數

    Field[] getDeclaredFields()//取得類別中所有的public和非public方法 
    常用的就這些,知道這些,其他的都好辦… 
五、用反射機制可以做什麼時侯,在寫存取資料庫時寫到想吐,有八個表,每個表都有增刪改查中操作 
    那時候還不知道有反射機制這個概念,所以就對不同的表創建不同的dao類,這樣不僅開發率地,而且代碼 
    冗餘的厲害,最要命的是看著差不多的,然後直接複製修改,由於容易犯各種低級的錯誤(大小寫啊,多一 
    個或少一個字母啊……),一個錯誤就可以讓你找半天。
        有了java反射機制,什麼都好辦了,只需要寫一個dao類,四個方法,增刪改查,傳入不同的對象,就OK啦, 
    無需為每個表創建dao類,反射機制會自動幫我們完成剩下的事情,這就是它的好處。說穿了,反射機制就是專門 
    幫我們做那些重複的有規則的事情,所以現在很多的自動生成代碼的軟體就是運用反射機制來完成的,只要你按照規則 
    輸入相關的參數,所以低階的程序員慢慢的就被抹殺了,為什麼?因為程式碼都不用寫了,隨便一個人都會開發,還要程 
    序員幹什麼啊?所以我們只有一條出路,就是努力努力再努力,成為高級程式設計師,專門開發傻瓜軟體,讓其他程式設計師  到一邊涼快去,呵呵~ 
六、用反射機制實現對資料庫資料的增、查例子 
基本原則;儲存資料時,先將需要儲存的物件的屬性值全部取出來再拼湊sql語句 
                 則以詢問時,並以並為資料資料包裝的資料全部包裝為一個java物件。
    遊戲規則:俗話說的好,無規矩不成方圓,特別是程序來說,它只能做有規則的事情,沒有規則的它乾不了,好,那就 
        資料庫的每一個表格物件一個pojo類,表中的每一個欄位對應pojo類別的中的一個屬性。 
              地方法。 
    有了遊戲規則,那就開始遊戲吧。

1、首先資料庫的有一個表,假設資料庫名稱為:blogsystem,裡面的一個表名userinfo。如圖:

2、創建對應的pojo類:Java反射機制

package cn.netjava.pojo;
 
public class UserInfo {
private int id;
private String name;
private String pwd;
private int age;
 
@Override
public String toString() {
    return "UserInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + ", age="
            + age + "]";
}
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 String getPwd() {
    return pwd;
}
public void setPwd(String pwd) {
    this.pwd = pwd;
}
public int getAge() {
    return age;
}
public void setAge(int age) {
    this.age = age;
}
 
}

2、編寫獲得資料庫連接的工廠類別:

package cn.netjava.factory;
 
import java.sql.Connection;
import java.sql.DriverManager;
 
public class Connect2DBFactory {
    public static Connection getDBConnection() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/blogsystem";
            String user = "root";
            String password = "netjava";
            conn = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return conn;
    }
}

3、好戲開始啦,編寫操作資料庫的dao類

package cn.netjava.session;
 
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
 
import cn.netjava.factory.Connect2DBFactory;
import cn.netjava.pojo.UserInfo;
 
public class NetJavaSession {
    /**
     * 解析出保存对象的sql语句
     *
     * @param object
     *            :需要保存的对象
     * @return:保存对象的sql语句
     */
    public static String getSaveObjectSql(Object object) {
        // 定义一个sql字符串
        String sql = "insert into ";
        // 得到对象的类
        Class c = object.getClass();
        // 得到对象中所有的方法
        Method[] methods = c.getMethods();
        // 得到对象中所有的属性
        Field[] fields = c.getFields();
        // 得到对象类的名字
        String cName = c.getName();
        // 从类的名字中解析出表名
        String tableName = cName.substring(cName.lastIndexOf(".") + 1,
                cName.length());
        sql += tableName + "(";
        List<String> mList = new ArrayList<String>();
        List vList = new ArrayList();
        for (Method method : methods) {
            String mName = method.getName();
            if (mName.startsWith("get") && !mName.startsWith("getClass")) {
                String fieldName = mName.substring(3, mName.length());
                mList.add(fieldName);
                System.out.println("字段名字----->" + fieldName);
                try {
                    Object value = method.invoke(object, null);
                    System.out.println("执行方法返回的值:" + value);
                    if (value instanceof String) {
                        vList.add("\"" + value + "\"");
                        System.out.println("字段值------>" + value);
                    } else {
                        vList.add(value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        for (int i = 0; i < mList.size(); i++) {
            if (i < mList.size() - 1) {
                sql += mList.get(i) + ",";
            } else {
                sql += mList.get(i) + ") values(";
            }
        }
        for (int i = 0; i < vList.size(); i++) {
            if (i < vList.size() - 1) {
                sql += vList.get(i) + ",";
            } else {
                sql += vList.get(i) + ")";
            }
        }
 
        return sql;
    }
 
    public static List getDatasFromDB(String tableName, int Id) {
 
        return null;
 
    }
 
    /**
     * 将对象保存到数据库中
     *
     * @param object
     *            :需要保存的对象
     * @return:方法执行的结果;1:表示成功,0:表示失败
     */
    public int saveObject(Object object) {
        Connection con = Connect2DBFactory.getDBConnection();
        String sql = getSaveObjectSql(object);
        try {
            // Statement statement=(Statement) con.createStatement();
            PreparedStatement psmt = con.prepareStatement(sql);
            psmt.executeUpdate();
            return 1;
        } catch (SQLException e) {
            e.printStackTrace();
            return 0;
        }
    }
 
    /**
     * 从数据库中取得对象
     *
     * @param arg0
     *            :对象所属的类
     * @param id
     *            :对象的id
     * @return:需要查找的对象
     */
    public Object getObject(String className, int Id) {
        // 得到表名字
        String tableName = className.substring(className.lastIndexOf(".") + 1,
                className.length());
        // 根据类名来创建Class对象
        Class c = null;
        try {
            c = Class.forName(className);
 
        } catch (ClassNotFoundException e1) {
 
            e1.printStackTrace();
        }
        // 拼凑查询sql语句
        String sql = "select * from " + tableName + " where Id=" + Id;
        System.out.println("查找sql语句:" + sql);
        // 获得数据库链接
        Connection con = Connect2DBFactory.getDBConnection();
        // 创建类的实例
        Object obj = null;
        try {
 
            Statement stm = con.createStatement();
            // 得到执行查寻语句返回的结果集
            ResultSet set = stm.executeQuery(sql);
            // 得到对象的方法数组
            Method[] methods = c.getMethods();
            // 遍历结果集
            while (set.next()) {
                obj = c.newInstance();
                // 遍历对象的方法
                for (Method method : methods) {
                    String methodName = method.getName();
                    // 如果对象的方法以set开头
                    if (methodName.startsWith("set")) {
                        // 根据方法名字得到数据表格中字段的名字
                        String columnName = methodName.substring(3,
                                methodName.length());
                        // 得到方法的参数类型
                        Class[] parmts = method.getParameterTypes();
                        if (parmts[0] == String.class) {
                            // 如果参数为String类型,则从结果集中按照列名取得对应的值,并且执行改set方法
                            method.invoke(obj, set.getString(columnName));
                        }
                        if (parmts[0] == int.class) {
                            method.invoke(obj, set.getInt(columnName));
                        }
                    }
 
                }
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

3、好戲開始啦,編寫操作資料庫的dao類

reee開始測試效果怎麼樣:

package cn.netjava.tester;
 
import cn.netjava.pojo.UserInfo;
import cn.netjava.session.NetJavaSession;
 
public class Tester {
    public static void main(String args[]) {
        //获得NetJavaSession对象
        NetJavaSession session = new NetJavaSession();
        //创建一个UserInfo对象
        UserInfo user = new UserInfo();
        //设置对象的属性
        user.setId(6988);
        user.setAge(44);
        user.setPwd("pwd");
        user.setName("champion");
        //将对象保存到数据库中
        String sql = session.getSaveObjectSql(user);
        System.out.println("保存对象的sql语句:" + sql);
        //查找对象
        UserInfo userInfo = (UserInfo) session.getObject(
                "cn.netjava.pojo.UserInfo", 6988);
        System.out.println("获取到的信息:" + userInfo);
 
    }
}

5、打印出來的結果:

Java反射機制七、總節一下

      總的來說,java反射機制是一個很好用的東西,用它可以解決很多死的東西,因為反射機制的彈性行很大,有了他,我們就不要花太多的時間來寫操做資料庫的程式碼了,而是方法更多的時間在專案的邏輯功能上,這個可以很大的減少開發時間,而且程式碼的可讀性好。先在的許多開源框架都是才用的反射機制,它只要配置文件,然後按規則來呼叫他的方法就可以了。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn