1. 反映メカニズムとは何ですか?
簡単に言えば、リフレクション メカニズムとは、プログラムが実行中に独自の情報を取得できることを意味します。 Java では、クラスの名前が指定されていれば、そのクラスに関するすべての情報をリフレクション メカニズムを通じて取得できます。
2. 反射メカニズムはどこで使用されますか?
場合によっては、ある程度の知識を使用することもありますが、専門用語が何であるかはわかりません。jdbc を学習したばかりのときは、Class.forName("com.mysql.jdbc.Driver.class") というコード行を使用しました。 newInstance() ; しかし、当時は、そのコード行がドライバー オブジェクト インスタンスを生成することだけを知っていて、その具体的な意味は知りませんでした。リフレクション機構についての授業を聞いて、これがリフレクションであることに気づきました。現在、多くのオープンフレームワークがリフレクション機構を使用しており、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)//指定されたパラメーターに従ってパブリック コンストラクターを取得します
Constructor[] getConstructors()//すべてのパブリック コンストラクターを取得します
Constructor getDeclaredConstructor(Class[] params)//指定されたパラメーターに基づいてパブリックおよび非パブリックのコンストラクターを取得します
Constructor[] getDeclaredConstructors()//すべてのパブリック コンストラクターを取得します
クラスメソッドのgetメソッド
メソッド getMethod(String name, Class[] params)、メソッド名とパラメータの型に基づいてメソッドを取得します
Method[] getMethods()//すべてのパブリック メソッドを取得します
Method getDeclaredMethod(String name, Class[] params)//メソッド名とパラメータの型に従って、パブリックメソッドと非パブリックメソッドを取得します
Method[] getDeclaredMethods()//すべてのパブリック メソッドと非パブリック メソッドを取得します
クラス内の属性を取得する方法
Field getField(String name)//変数名に従って対応するパブリック変数を取得します
Field[] getFields()//クラス内のすべてのパブリック メソッドを取得します
Field getDeclaredField(String name)//メソッド名に基づいてパブリック変数と非パブリック変数を取得します
Field[] getDeclaredFields()//クラス内のすべてのパブリックおよび非パブリック メソッドを取得します
これらは一般的に使用されるものであり、これらを知っていれば、他のものはすべて簡単に処理できます。
5. 反映メカニズムで何ができるのですか?
jdbc を使い始めた頃は、データベースにアクセスするための書き込みをするときに吐きそうになりました。テーブルが 8 つあり、それぞれのテーブルに追加、削除、変更、検索の操作がありました。当時は、という概念を知りませんでした。リフレクション メカニズムを使用するため、表にさまざまな DAO クラスの作成について書きました。これにより、開発が高速化されるだけでなく、コードが冗長になります。それらがほぼ同じに見えるため、それらを直接コピーして変更することになります。さまざまな低レベルの間違い (大文字と小文字、もう 1 文字、または 1 文字足りないなど) を犯しやすいため、1 つの間違いを見つけるのに時間がかかることがあります。
Java のリフレクション機構を使用すると、追加、削除、変更、クエリの 4 つのメソッドを使用して dao クラスを作成し、別のオブジェクトを渡すだけですべてが簡単になります。各テーブルの dao クラスを使用すると、リフレクション メカニズムが残りの作業を自動的に実行します。これが利点です。率直に言うと、リフレクション メカニズムは、反復的かつ定期的な処理を支援するように設計されているため、コードを自動生成する多くのソフトウェアは、規則に従って関連するパラメーターを入力する限り、コードを完了するためにリフレクション メカニズムを使用しています。レベルのプログラマは遅い 遅いプログラマは抹殺されました、なぜですか?コードを書く必要がないので誰でも開発できるのに、なぜプログラマーが開発するのでしょうか?だから、私たちに解決策は一つしかありません。それは、一生懸命働いて、上級プログラマーになって、愚かなソフトウェアの開発に特化して、他のプログラマーは脇に置いて冷静になることです、はは~
6. 反映機構を利用したデータベースデータの追加・確認例
基本原則: データを保存するときは、保存する必要があるオブジェクトのすべての属性値を取り出し、クエリ用の SQL ステートメントをまとめ、クエリされたすべてのデータを Java オブジェクトにパッケージ化します。
ゲームのルール: 格言にあるように、特にプログラムでは、ルールがなければ何もできません。まずルールを設定しましょう。
1)データベース内の各テーブル オブジェクトには pojo クラスがあり、テーブル内の各フィールドは pojo クラスの属性に対応します。さらに、pojo クラスの名前はテーブルの名前と同じであり、属性名とフィールド名も同じです。データベースでは通常、大文字と小文字が区別されないためです。
2) pojo クラスの各属性に標準の set メソッドと get メソッドを追加します。
ゲームのルールを理解したら、ゲームを始めましょう。
1. まず、データベース内にテーブルがあり、データベース名が blogsystem であり、そのテーブル名が userinfo であるとします。図に示すように:
2. 対応する pojo クラスを作成します。
次のようにコードをコピーします。
パッケージ cn.netjava.pojo;
パブリック クラス UserInfo {
プライベート int ID;
プライベート文字列名。
プライベート文字列 pwd;
プライベートの年齢。
@オーバーライド
public String toString() {
return "UserInfo [id=" + id + "、name=" + name + "、pwd=" + pwd + "、age="
+ 年齢 + "]";
}
public int getId() {
ID を返します。
}
public void setId(int id) {
this.id = ID;
}
public String getName() {
名前を返します。
}
public void setName(文字列名) {
this.name = 名前;
}
パブリック String getPwd() {
パスワードを返します。
}
public void setPwd(String pwd) {
this.pwd = パスワード;
}
public int getAge() {
年齢を返す。
}
public void setAge(int age) {
this.age = 年齢;
}
}
2. データベース接続を取得するためのファクトリ クラスを作成します。
次のようにコードをコピーします。
パッケージ cn.netjava.factory;
java.sql.Connectionをインポートします。
java.sql.DriverManagerをインポートします。
パブリック クラス Connect2DBFactory {
パブリック静的接続 getDBConnection() {
接続 conn = null;
試す {
Class.forName("com.mysql.jdbc.Driver");
文字列 URL = "jdbc:mysql://localhost:3306/blogsystem";
文字列ユーザー = "ルート";
文字列パスワード = "netjava";
conn = DriverManager.getConnection(url, ユーザー, パスワード);
} catch (例外 e) {
e.printStackTrace();
}
コンを返します。
}
}
3. 楽しい作業が始まります。データベースを操作する dao クラスを作成します。
次のようにコードをコピーします。
パッケージ cn.netjava.session;
java.lang.reflect.Fieldをインポートします。
java.lang.reflect.Methodをインポートします。
java.sql.Connectionをインポートします。
インポートjava.sql.PreparedStatement;
インポートjava.sql.ResultSet;
インポート java.sql.SQLException;
java.sql.Statementをインポートします。
java.util.ArrayListをインポートします。
java.util.Listをインポートします。
cn.netjava.factory.Connect2DBFactoryをインポートします。
cn.netjava.pojo.UserInfoをインポートします。
パブリック クラス NetJavaSession {
/**
* オブジェクトを保存する SQL ステートメントを解析します。
*
* @param オブジェクト
*: 保存が必要なオブジェクト
* @return: オブジェクトを保存する SQL ステートメント
*/
public static String getSaveObjectSql(Object オブジェクト) {
//SQL文字列を定義する
文字列 sql = "に挿入";
// オブジェクトのクラスを取得します
クラス c = object.getClass();
// オブジェクト内のすべてのメソッドを取得します
Method[] メソッド = c.getMethods();
// オブジェクト内のすべてのプロパティを取得します
フィールド[] フィールド = c.getFields();
// オブジェクトクラスの名前を取得します
文字列 cName = c.getName();
// クラス名からテーブル名を解析します
文字列テーブル名 = cName.substring(cName.lastIndexOf(".") + 1,
cName.length());
SQL += テーブル名 + "(";
List<String> mList = new ArrayList<String>();
リスト vList = 新しい ArrayList();
for (メソッド メソッド : メソッド) {
文字列 mName = メソッド.getName();
if (mName.startsWith("get") && !mName.startsWith("getClass")) {
文字列フィールド名 = mName.substring(3, mName.length());
mList.add(フィールド名);
System.out.println("フィールド名----->" + フィールド名);
試す {
オブジェクト値 = method.invoke(object, null);
System.out.println("実行メソッドによって返される値: " + 値);
if (文字列の値インスタンス) {
vList.add("/"" + 値 + "/"");
System.out.println("フィールド値------>" + 値);
} それ以外 {
vList.add(値);
}
} catch (例外 e) {
e.printStackTrace();
}
}
}
for (int i = 0; i < mList.size(); i++) {
if (i < mList.size() - 1) {
sql += mList.get(i) + ",";
} それ以外 {
sql += mList.get(i) + ") 値(";
}
}
for (int i = 0; i < vList.size(); i++) {
if (i < vList.size() - 1) {
sql += vList.get(i) + ",";
} それ以外 {
sql += vList.get(i) + ")";
}
}
SQLを返します。
}
public static List getDatasFromDB(String tableName, int Id) {
null を返します。
}
/**
* オブジェクトをデータベースに保存します
*
* @param オブジェクト
*: 保存が必要なオブジェクト
* @return: メソッドの実行結果。1: 成功を示し、0: 失敗を示します。
*/
public int saveObject(Object オブジェクト) {
接続 con = Connect2DBFactory.getDBConnection();
文字列 sql = getSaveObjectSql(オブジェクト);
試す {
// ステートメント state=(Statement) con.createStatement();
PreparedStatement psmt = con.prepareStatement(sql);
psmt.executeUpdate();
1を返します。
} キャッチ (SQLException e) {
e.printStackTrace();
0を返します。
}
}
/**
* データベースからオブジェクトを取得します
*
* @パラメータ引数0
*: オブジェクトが属するクラス
* @パラメータID
*: オブジェクトのID
* @return: 検索するオブジェクト
*/
public Object getObject(String className, int Id) {
// テーブル名を取得する
文字列テーブル名 = className.substring(className.lastIndexOf(".") + 1,
クラス名.length());
// クラス名に基づいて Class オブジェクトを作成
クラス c = null;
試す {
c = クラス.forName(クラス名);
} キャッチ (ClassNotFoundException e1) {
e1.printStackTrace();
}
// クエリ SQL ステートメントを結合します
String sql = "select * from " + tableName + " where Id=" + Id;
System.out.println("SQL ステートメントの検索: " + sql);
// データベースリンクを取得
接続 con = Connect2DBFactory.getDBConnection();
//クラスのインスタンスを作成する
オブジェクトobj = null;
試す {
ステートメント stm = con.createStatement();
// 検索ステートメントを実行して返された結果セットを取得します
ResultSet セット = stm.executeQuery(sql);
// オブジェクトのメソッド配列を取得します
Method[] メソッド = c.getMethods();
// 結果セットを走査します
while (set.next()) {
obj = c.newInstance();
//オブジェクトを走査するメソッド
for (メソッド メソッド : メソッド) {
文字列メソッド名 = メソッド.getName();
// オブジェクトのメソッドが set で始まる場合
if (メソッド名.startsWith("set")) {
// メソッド名に基づいてデータテーブル内のフィールドの名前を取得します
文字列列名 = メソッド名.substring(3,
メソッド名.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 (例外 e) {
e.printStackTrace();
}
オブジェクトを返します。
}
}
4. テストを開始した場合の効果はどうですか:
次のようにコードをコピーします。
パッケージ cn.netjava.tester;
cn.netjava.pojo.UserInfoをインポートします。
cn.netjava.session.NetJavaSession をインポートします。
パブリック クラス テスター {
public static void main(String args[]) {
// NetJavaSession オブジェクトを取得する
NetJavaSession セッション = new NetJavaSession();
//UserInfo オブジェクトを作成する
UserInfo ユーザー = new UserInfo();
// オブジェクトのプロパティを設定します
user.setId(6988);
user.setAge(44);
user.setPwd("pwd");
user.setName("チャンピオン");
// オブジェクトをデータベースに保存します
文字列 sql = session.getSaveObjectSql(user);
System.out.println("オブジェクトを保存する SQL ステートメント: " + sql);
//オブジェクトを検索
ユーザー情報 userInfo = (ユーザー情報) session.getObject(
"cn.netjava.pojo.UserInfo"、6988);
System.out.println("取得した情報: " + userInfo);
}
}
5. 印刷結果:
7. まとめてみましょう
一般に、Java リフレクション メカニズムは非常に柔軟なので、データベース コードを使用する代わりに、多くの無駄な問題を解決できます。このメソッドはプロジェクトの論理関数により多くの時間を費やすため、開発時間が大幅に短縮され、コードが読みやすくなります。既存のオープンソース フレームワークの多くは、ファイルを設定して、ルールに従ってメソッドを呼び出すだけで済みます。