Java リフレクション メカニズム

高洛峰
リリース: 2016-12-12 11:36:53
オリジナル
1240 人が閲覧しました

1. リフレクション メカニズムとは何ですか? 簡単に言うと、プログラムが実行中に独自の情報を取得できることを意味します。 Java では、クラスの名前が指定されていれば、
リフレクション機構を通じてクラスのすべての情報を取得できます。
2. リフレクション メカニズムを使用する場所
いくつかの知識を使用することがありますが、その専門用語が何であるかはわかりません。jdbc を学んだばかりのときは、コード行
Class.forName("com) を使用しました。 .mysql.jdbc .Driver.class").newInstance(); しかし、当時は、そのコード行が
ドライバー オブジェクト インスタンスを生成することだけを知っていて、その具体的な意味は知りませんでした。リフレクション機構についての授業を聞いて、これがリフレクションであることに気づきました。現在、多くのオープンフレームワークがリフレクション機構を使用しており、Struts もすべてリフレクション機構を使用して実装されています。
3. リフレクション メカニズムのメリットとデメリット
リフレクション メカニズムを使用する理由オブジェクトを直接作成するだけでは十分ではないでしょうか? これには、動的と静的の概念が含まれます。
静的コンパイル: コンパイル時に型を決定し、オブジェクトをバインドします。
動的コンパイル: 型を決定し、実行時にオブジェクトをバインドします。動的コンパイルは Java の柔軟性を最大限に高め、ポ​​リモーフィックなアプリケーションを具体化し、クラス間の結合を軽減します。
一言で言えば、リフレクション メカニズムの利点は、動的にオブジェクトを作成してコンパイルできることであり、特に J2EE の開発において優れた柔軟性を発揮します
その柔軟性は非常に明白です。たとえば、大規模なソフトウェアの場合、一度に完璧に設計することは不可能です。プログラムをコンパイルしてリリースした後、特定の機能を更新する必要があることが判明した場合、ユーザーに以前のソフトウェアをアンインストールするように求めることはできません。
この場合は、新しいバージョンを再インストールしてください。このソフトウェアは多くの人には使用されないでしょう。静的な場合、関数を更新する前にプログラム全体を 1 回再コンパイルする必要があります。リフレクション メカニズムを使用している場合は、関数を実現するために動的に作成してコンパイルするだけで済みます。 。
欠点は、パフォーマンスに影響することです。リフレクションの使用は基本的に解釈された操作であり、やりたいことを JVM に伝えることができ、それが要件を満たします。このような操作は、同じ操作を直接実行するよりも常に遅くなります。
4. リフレクションメカニズムを使用するとどのような情報を取得できますか? Class オブジェクトを作成するクラスの完全な名前。
Class c=Class.forName("className"); 注: className は完全な名前である必要があります。つまり、パッケージ名が含まれている必要があります (例: cn.netjava.pojo.UserInfo)。
Object obj=c.newInstance; ();/ / オブジェクトのインスタンスを作成します
OK、オブジェクトを取得したら、すべての操作は簡単で、必要な情報はすべて取得できます。
コンストラクターを取得するメソッド
Constructor getConstructor(Class[] params)//指定されたパラメーターに従ってパブリックコンストラクターを取得します

Constructor[] getConstructors()//すべてのパブリックコンストラクターを取得します

Constructor getDeclaredConstructor(Class[] params ) //指定されたパラメーターに従ってパブリックおよび非パブリックのコンストラクターを取得します

Constructor[] getDeclaredConstructors()//すべてのパブリック コンストラクターを取得します
クラスメソッドのメソッドを取得します
Method getMethod(String name, Class[] params), according toメソッド名、パラメータの型にメソッドを取得します

Method[] getMethods()//すべてのパブリックメソッドを取得します

Method getDeclaredMethod(String name, Class[] params)//メソッド名とパラメータの型に従って、getパブリックメソッドと非パブリックメソッド

Method[] getDeclaredMethods()// すべてのパブリックメソッドと非パブリックメソッドを取得します

クラス内の属性を取得するメソッド
Field getField(String name)// 以下に従って、対応するパブリック変数を取得します変数名

Field[] getFields()/ /クラス内のすべてのパブリック メソッドを取得します

Field getDeclaredField(String name)//メソッド名に従ってパブリック変数と非パブリック変数を取得します

Field[] getDeclaredFields()//クラス内のすべてのパブリック メソッドと非パブリック メソッドを取得します
これらが一般的に使用されるメソッドです。これらを知っていれば、他のことは簡単です...
5. を使用して何ができますか。反映機構
私はjdbcを使い始めたばかりで、データベースにアクセスするために書いているとき、8つのテーブルがあり、それぞれのテーブルに追加、削除、変更、確認の操作がありました
そのとき、私はリフレクション メカニズムの概念を知らなかったので、クラスごとに異なる DAO を作成しました。これにより、開発が高速化されるだけでなく、コードが非常に冗長になります。それを直接コピーして修正すると、あらゆる種類の低レベルの間違い (大文字と小文字の場合、
が 1 つ増えたり、文字が 1 つ減ったりする...) を犯しやすく、1 つの間違いで長い時間がかかる可能性があります。把握するため。反 Java リフレクション メカニズムを使用すると、DAO クラス、追加、削除、調査を記述するだけで、残りの作業が自動的に行われます。これが利点です。率直に言うと、リフレクション メカニズムは、反復的かつ定期的な処理を支援するためのものです
ので、現在、コードを自動生成する多くのソフトウェアは、ルール
に従って関連するパラメーターを入力する限り、リフレクション メカニズムを使用して実行されます。低レベルのプログラムのメンバーは徐々に全滅していったのですが、なぜですか?コードを書く必要がないので誰でも開発できるのに、なぜプログラマーが必要なのでしょうか?したがって、私たちに解決策は 1 つしかありません。それは、一生懸命働いて上級プログラマーになり、愚かなソフトウェアの開発に特化し、他のプログラマーは脇に置いて冷静になることです、笑~
6. リフレクション メカニズムを使用してデータベースを追加しますデータ、例を確認してください
基本原則; データを保存するときは、保存する必要があるオブジェクトのすべての属性値を取り出し、クエリを実行するときに、クエリされたすべてのデータを Java オブジェクトにパッケージ化します。 。
ゲームのルール: 格言にあるように、特にプログラムの場合は、ルールがある場合のみ実行でき、ルールがなければ実行できません。それでは
テーブル オブジェクトは pojo クラスです。 、テーブル内の各フィールドは、pojo クラスの属性に対応します。
そして、pojo クラスの名前はテーブルの名前と同じで、属性名とフィールド名も同じです。データベースは通常大文字と小文字を区別しないため、大文字と小文字は関係ありません
2) 標準セットを追加しますそして、pojo クラスの各属性のメソッドを取得します。
ゲームのルールを理解したら、ゲームを始めましょう。

1. まず、データベース名が blogsystem で、その中のテーブル名が userinfo であるとします。図に示すように:



2. 対応する pojo クラスを作成します:

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;
    }
}
ログイン後にコピー
Java リフレクション メカニズム3. 楽しい作業が始まります。データベース

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;
    }
}
ログイン後にコピー

4. テスト開始の効果はどうですか:

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. 出力された結果:

7. まとめ

一般的に言えば、Java リフレクション メカニズムは非常に便利なものであり、問​​題を解決できます。リフレクション メカニズムは非常に柔軟であるため、データベースを操作するためのコードの作成に多くの時間を費やす必要がなく、プロジェクトの論理機能により多くの時間を費やすことができます。開発時間を短縮し、コードを読みやすくします。既存のオープンソース フレームワークの多くは、ファイルを設定して、ルールに従ってメソッドを呼び出すだけで済みます。

Java リフレクション メカニズム

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート