Java における Java 言語のリフレクション メカニズム:
実行状態では、Java リフレクション メカニズムは、あらゆるクラス (クラス ファイル) のすべての属性とメソッドを知ることができます。
あらゆるオブジェクトについて、その Any メソッドと属性を呼び出すことができます。
この動的に取得される情報とオブジェクトのメソッドを動的に呼び出す運動エネルギーをJava言語のリフレクション機構と呼びます。
クラス内の情報の動的な取得は Java リフレクションであり、これによりクラスの構造を理解することができます。一部のアプリケーションは、新しいオブジェクトを作成できませんが、クラスを動的にロードしてクラス情報を取得できます。
図に示すように、クラスがオブジェクトの記述であるのと同様に、Class クラスはバイトコード ファイル (.class ファイル) オブジェクトを記述することができます。
//初期: 新しいときは、まず新しいクラスの名前に基づいてクラスのバイトコード ファイルを見つけてメモリにロードします。
//バイトコード ファイル オブジェクトを作成し、次にバイトコード ファイルの対応する Person オブジェクト。
com.xidian.person p=new com.xidian.person();
//今
String name="com.xidian.person";
//ファイルクラスファイルを見つけてメモリにロードし、クラスオブジェクトを生成します。
Class clazz=Class.forName(name);
//このクラスのオブジェクトを生成するには?
Object obj=clazz.newInstance();
リフレクティブクラスロードメソッドを使用すると、形式は表面的にはより複雑になりますが、スケーラビリティはより強力になります。以前は、プログラム ファイルにオブジェクトを手動で作成する必要がありましたが、現在は構成ファイルに文字列を記述するだけで、対応するオブジェクトを作成できます。
質問: clazz.newInstance() を使用すると、空のパラメーター コンストラクターのみを使用できます。パラメーター リスト コンストラクターを使用したい場合はどうすればよいですか?
/*
* 指定された名前に対応するクラスに組み込まれたオブジェクトを取得する際、* 空のパラメータコンストラクタを使用せずにオブジェクトが初期化された場合はどうすればよいでしょうか?
*
* オブジェクトは指定されたコンストラクター
* を通じて初期化されるため、最初にコンストラクターを取得する必要があります。これはバイトコード ファイルを通じて実行できます。
* メソッドは次のとおりです: getConstructor(parameterTypes)
*
* リフレクションでは、コンストラクター、フィールド、メソッドはすべてオブジェクトです。
*/
String name="com.xidian.person";
Class clazz=Class.forName(name);
//指定されたコンストラクターオブジェクトを取得します
Constructorconstructor=clazz.getConstructor(String.class,int .class ); //すべてのデータ型はバイトコード ファイルで記述できます。 .class
//オブジェクトはコンストラクター オブジェクトの newInstance メソッドを通じて初期化されます。
Object obj=constructor.newInstance("xiaoming",12);
指定されたフィールドの値を取得します:
//プライベートフィールドにアクセスするための学校全体の権限を確認します。暴力的なアクセス。
field_1.setAccessible(true);
Object obj=clazz.newInstance();
field_1.set(obj,88);
Object o=field_1.get(obj);
System.out.println(o ; );
Method Method2=clazz.getMethod("paramMethod",String.class,int.class); //パラメータ、メソッド名、パラメータリストを含むメソッドを取得する
method2 .invoke(obj2, "Xiaoqiang",89); //invoke: 指定されたオブジェクト上で、指定されたパラメータを使用して、この Method オブジェクトによって表される基になるメソッドを呼び出します。
リフレクションの適用:
インターフェイスの定義:
package com.xidian; public interface PCI { public void open(); public void close(); }
package com.xidian; public class SoundCard implements PCI{ public void open(){ System.out.println("sound open"); } public void close(){ System.out.println("sound close"); } }
package com.xidian; public class Mainboard { public void run(){ System.out.println("main run..."); } public void usePCI(PCI p){ if(p!=null){ p.open(); p.close(); } } }
テスト:
package com.xidian; public class Test { public static void main(String[] args){ Mainboard mb=new Mainboard(); mb.run(); mb.usePCI(new SoundCard()); //如果主板需要使用其他设备,必须重新修改代码,传递一个新创建的对象,可扩展性不好。 } }
インターフェイスの使用により、プログラムの程度は良いですが、コードの拡張性は良くありません。
デバイスをマザーボードに追加したいが、コードを変更したくない場合は、代わりにリフレクションを使用してください:
それを完了するために new を使用する必要はありませんが、クラス ファイルとその内部のクラス ファイルを取得するだけで済みます。オブジェクトを作成するアクションです。
リフレクションを使用した構成には .xml を使用する必要があります。これにより、より正確になります。ここでは、プロパティ オブジェクトを使用してそれを実現します。
メイン関数コードを変更します:
public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{ Mainboard mb=new Mainboard(); mb.run(); //mb.usePCI(new SoundCard()); //如果主板需要使用其他设备,必须重新修改代码,可扩展性不好。 File configFile=new File("pci.properties"); Properties prop=new Properties(); //注意是将配置文件放在项目的一级目录下。 FileInputStream fis=new FileInputStream(configFile); prop.load(fis); for(int x=0;x<prop.size();x++){ String pciName=prop.getProperty("pci"+(x+1)); Class clazz=Class.forName(pciName); PCI p=(PCI)clazz.newInstance(); mb.usePCI(p); } fis.close(); } }
設定ファイル pci.properties: pci1=com.xidian.SoundCard
デバイスを拡張する場合、メイン プログラムのコードを変更することなく、デバイス プログラムと設定ファイルを記述するだけで済みます。使用する準備ができています。