反射の原則を理解するには、まず情報の種類を理解する必要があります。 Javaを使用すると、実行時にオブジェクトとクラスの情報を特定できます。主に2つの方法があります。1つは従来のRTTIです。これは、コンパイル時にすべてのタイプ情報をすでに知っていると想定しています。もう1つは反射メカニズムです。これにより、実行時にクラスの情報を発見して使用できます。
1。クラスオブジェクト
JavaでRTTIがどのように機能するかを理解するには、まず実行時にタイプ情報がどのように表現されるかを知る必要があります。これは、クラスに関連する情報を含むクラスオブジェクトによって行われます。クラスオブジェクトは、すべての「通常の」オブジェクトを作成するために使用されます。 Javaは、型変換などの操作を実行している場合でも、クラスオブジェクトを使用してRTTIを実行します。
各クラスは、Classファイルに保存される対応するクラスオブジェクトを生成します。すべてのクラスは、初めて使用されるときにJVMに動的にロードされます。このクラスは、プログラムがクラスの静的メンバーへの参照を作成するときにロードされます。クラスオブジェクトは必要なときにのみロードされ、クラスがロードされたときに静的初期化が実行されます。
public class testmain {public static void main(string [] args){system.out.println(xyz.name);}} class xyz {public static string name = "luoxn28"; static {system.out.println( "xyz static block");構築された ");}}出力の結果は次のとおりです。
クラスローダーは、最初にこのクラスのクラスオブジェクトがロードされているかどうかを確認します。ロードされていない場合、デフォルトのクラスローダーは、クラス名に基づいて対応する。クラスファイルを検索します。
実行時にタイプ情報を使用するには、オブジェクトのクラスオブジェクト(ベースオブジェクトなど)への参照を取得する必要があります。 function class.forname( "base")を使用してこれを達成するか、base.classを使用できます。面白いことに注意してください。関数「.class」を使用してクラスオブジェクトへの参照を作成する場合、クラスオブジェクトは自動的に初期化されず、forname()を使用するとクラスオブジェクトが自動的に初期化されます。クラスを使用するための準備には、一般に次の3つのステップがあります。
•ロード:クラスローダーで完了し、対応するバイトコードを見つけ、クラスオブジェクトを作成します
•リンク:クラスのバイトコードを確認し、静的ドメインにスペースを割り当てます
•初期化:クラスにスーパークラスがある場合、初期化され、静的初期化と静的初期化ブロックが実行されます。
public class base {static int num = 1; static {system.out.println( "base" + num);}} public class main {public static void main(string [] args){//静的ブロックは初期化されません。 class.forname( "zzz.base");}} 2。タイプ変換の前に確認してください
コンパイラは、タイプの下向きのトランジションが合法かどうかを確認し、合法でない場合は例外がスローされます。タイプダウンを変換する前に、instanceofを使用して判断することができます。
クラスベース{}クラス派生拡張ベース{} public class main {public static void main(string [] args){base base = new derived(); if(base instanceof derived){// 3。反射:ランタイム情報
オブジェクトの正確なタイプがわからない場合は、rttiが伝えることができますが、前提条件があります。このタイプは、RTTIを使用して識別できるようにコンパイル時間に既知でなければなりません。クラスクラスは、java.lang.Reflectクラスライブラリと一緒に反射をサポートしています。このクラスライブラリには、フィールド、メソッド、およびコンストラクタークラスが含まれています。これらのクラスのオブジェクトは、StartupのJVMによって作成され、不明なクラスの対応するメンバーを表します。このようにして、Contructorを使用して新しいオブジェクトを作成し、get()およびset()メソッドを使用してクラスのフィールドオブジェクトに関連付けられたフィールドを取得および変更し、Invoke()メソッドを使用してメソッドオブジェクトに関連付けられたメソッドを呼び出すことができます。さらに、getFields()、getMethods()、getConstructors()などの多くの便利な方法を呼び出すこともできます。このようにして、コンパイル時にクラスについて何も知らずに、実行時にオブジェクト情報を完全に決定できます。
反射メカニズムについて魔法のようなものはありません。反射を介して未知のタイプのオブジェクトを扱うとき、JVMは単にオブジェクトをチェックして、どの特定のクラスに属するかを確認します。したがって、そのクラスのクラスは、ローカルマシンまたはネットワークのいずれかで、JVMに対してフェッチ可能でなければなりません。したがって、RTTIと反射の本当の違いは次のとおりです。
•RTTI、コンパイラが開き、コンパイル時にクラスファイルをチェックします
•実行時にファイルを反映、開き、チェックします
パブリッククラスの人はシリアル化可能{private string name; private int age; // get/set method} public static void main(string [] args){person person = new person( "luoxn28"、23); class clazz = person.getclass(); field [] fields = clazz.getdeclaredfields();(フィールド:フィールド: DESCRIPTOR = new PropertyDescriptor(key、clazz); method method = descriptor.getReadmethod(); object value = method.invoke(person); system.out.println(key + ":" + value);}}}上記は、getReadMethod()メソッドを介してクラスのGet関数を呼び出し、getWriteMethod()メソッドを使用してクラスの設定メソッドを呼び出すことができます。一般的に言えば、反射ツールを使用する必要はありませんが、動的コードの作成にはより便利です。 Javaでは、Object SerializationやJavabeansなどの他の機能をサポートするためにJavaで使用されます。
4。ダイナミックエージェント
プロキシモードは追加または異なる操作を提供することであり、挿入されたオブジェクトは、「実際の」オブジェクトとの通信を含む「実際の」オブジェクトを置き換えるために使用されるため、通常、プロキシは仲介者として機能します。 Javaのダイナミックプロキシは、プロキシのアイデアの一歩先を行っています。プロキシは、動的にプロキシを作成およびプロキシメソッドへの呼び出しを動的に処理できます。ダイナミックプロキシで行われたすべての呼び出しは、単一のコールプロセッサにリダイレクトされ、その仕事はコールのタイプを明らかにし、対応するポリシーを決定することです。動的プロキシの例は次のとおりです。
インターフェイスと実装クラス:
public interface interface {void dosomething(); void anythingelse(string arg);} public class realobject emplestion interface {public void dosomething(){system.out.println( "dosomething。");} public void anythingElse(string arg.out){system.out.println(動的プロキシオブジェクトプロセッサ:
パブリッククラスDynamicProxyHandler InvocationHandler {private Object proxyed; public dynamicProxyhandler(Object Proxyed){this.proxyed = proxyed;}@overridepublicオブジェクト(オブジェクトプロキシ、メソッドメソッド、オブジェクト[] {system.out.println( "プロキシが動作しています。"); return method.invoke(proxyed、args);}}}テストクラス:
public class main {public static void main(string [] args){realobject real = new realobject(); interface proxy =(interface)proxy.newproxyinstance(interface.class.getClassoloaser()、new class [] {interface.class}、new dynamicProxyHandler(real)); proxy.dosomething(); proxy.somethingelse( "luoxn28");}}}出力の結果は次のとおりです。
Proxy Static Method Proxy.newProxyInstance()を呼び出すことにより、動的プロキシを作成できます。この方法では、クラスローダー、プロキシを実装するインターフェイスのリスト(クラスや抽象クラスではなく)、およびInvocationHandlerの実装クラスが必要です。ダイナミックプロキシはすべての呼び出しを呼び出しプロセッサにリダイレクトできます。そのため、コールプロセッサのコンストラクターは通常、「実際の」オブジェクトへの参照を渡します。これにより、コールプロセッサが調停タスクを実行しているときにリクエストが転送されます。
上記は、編集者が紹介したJava Reflectionの詳細な理解です。それがあなたに役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!