リフレクション
Reflectionは、プログラムがReflectionAPIを使用して実行中に任意のクラスの内部情報を取得し、任意のオブジェクトの内部プロパティとメソッドを直接操作できるようにします
クラスをロードした後、タイプClassのオブジェクトがヒープメモリのメソッド領域に生成されます
注意してください!クラスは、クラス型の対応するインスタンスを1つだけ持つことができます
このオブジェクトは、クラスの完全な構造情報をカプセル化します。このクラスオブジェクトを通じてクラスの構造を確認できます
動的言語と静的言語の違い:
動的言語
構造の言語は実行時に変更でき、新しい関数、オブジェクト、およびコードを実行時に追加できます
既存の関数は削除または変更でき、ランタイムコードは特定の条件に従って構造を変更できます
主な言語:Object-C、C#、JavaScript、PHP、Python、Eriang
静的言語
実行時にコードを変更できないプログラミング言語は静的言語です:Java、C、C ++
Javaは静的言語ですが、リフレクションメカニズムはJavaを動的に見せることができます。!!
リフレクションメカニズムによって提供される機能:
-オブジェクトが属するクラスを決定する
-実行時にクラスのインスタンスを作成する
-クラスのすべてのメンバー変数とメソッドを決定する
-一般的な情報を取得する
-任意のインスタンスのメンバー変数とメソッドを呼び出す
-実行時に注釈を処理する
-動的プロキシ!!!
API
-java.lang.Classクラスタイプクラス
-java.lang.reflect.Methodメソッドクラス
-java.lang.reflect.Fieldフィールドクラス
-java.lang.reflect.Construtorコンストラクタクラス
カスタムクラスを宣言します
パブリック クラスPerson { プライベート文字列名; プライベート int型の年齢; プライベート ブールジェンダー。 public Person(){ } public Person(String name、int age、boolean gender){ this .name = name; この .age = 年齢; this .gender = gender; } public String getName(){ 戻り名; } public void setName(String name){ this.name = 名前; } public int getAge(){ 年齢を返す; } public void setAge(int age){ this .age = age; } public boolean isGender(){ 性別を返す; } public void setGender(boolean gender){ this .gender = gender; } @Override public String toString(){ return "Person {" + "name = '" + name +' \ '' + "、age =" + age + "、gender =" + gender + '}' ; } }
クラスおよびインスタンス操作へのアクセスを実現するためのリフレクションを通じて
パブリック クラスReflectTest { @Test 公共 のボイド(反映)がスロー例外{ // クラスのプロパティは、クラスのクラスオブジェクトを返します 。クラス<人> = personClass人クラス; //は、買収、このクラスのオブジェクトコンストラクタクラスを取得します全引数のコンストラクタ コンストラクタ<人> personClassConstructor = personClass.getConstructor(文字列。クラス、int型。クラス、ブール値。クラス); // Personオブジェクトを作成し、コンストラクタを呼び出す 人の人= personClassConstructor.newInstanceを( "Jiege" 28 、true ); //PersonオブジェクトのtoString()を呼び出す; System.out.println(person.toString()); // リフレクションを通じて、オブジェクト、メソッド Fieldで指定されたプロパティを呼び出す age = personClass.getDeclaredField( "age" ); // アクセスのロックを解除するアクセス許可はアクセス前に設定する必要があります。それ以外の場合は意味がありません age.setAccessible(true ); // クラスのクラスフィールドインスタンスを介して、パラメーターインスタンスのageフィールドを呼び出し、値を変更します // 例外エラープライベートにアクセスできないことを検出しました // クラスcn.dai.Reflection .ReflectTestは、修飾子 "private"を 使用してクラスcn.dai.Reflection.Personのメンバーにアクセスできません age.set(person、10 ); System.out.println(person); } }
たとえば、メソッド、コンストラクタ、これらは基本的に、対応するカプセル化クラスを取得し、カプセル化クラスのインスタンスを取得して、メソッドを呼び出します。
非公開で変更されたアクセス権の場合は、使用する前にカプセル化されたインスタンスのアクセシビリティを設定してから、呼び出しを実行します
クラス読み込みプロセス:
-バイトコードがjava.exeを通過した後、1つ以上のバイトコードファイルがソースコードによって記述された内容に従って生成されます
-java.exeはバイトコードファイルに従って解釈および実行します==バイトコードがメモリにロードされます
-上記のこのステップはクラスローディングと呼ばれます
-ランタイムクラスと呼ばれる、メモリに読み込まれたクラスは、Classクラスのインスタンスとして存在します
-逆に、Classのオブジェクトは、JVMで実行されているバイトコードクラスです。
クラスインスタンスを取得する4つの方法:
パブリック クラスGetClassStyle { @Test 公共 ボイド getClass4Way()がスロー例外{ // 第一のタイプの.class クラスの<person> = personClass1人クラス、 のSystem.out.println(personClass1); // 第二種の例.getClassを( ); 人人= 新しい新しい人(); クラスは、 <?拡張 personClass2人を=> person.getClass(); System.out.printlnは(personClass2); // 第三Class.forNameの完全修飾名(クラス) クラス< ?> personClass3 = Class.forName( "cn.dai.Reflection.Person"); System.out.printlnは(personClass3); // 第四現在のクラス.class.getClassLoader()完全修飾名にloadClass(クラス「);. PersonClass4 = GetClassStyleクラス<?>。クラス .getClassLoader()はloadClass。 ( "cn.dai.Reflection.Person" ); // 呼び出されたメソッドのすべてのインスタンスは同じオブジェクトです } }
ClassLoaderを使用して構成ファイルをロードする
public class Loader { @Test public void loader()throws Exception { Properties properties = new Properties(); // ストリームオブジェクトは、現在のソースプロジェクトディレクトリでのみ読み取ることができます。読み取りたい場合は、パスを「src \」として書き込む必要があります\ jdbc.properties " FileInputStream inputStream = new FileInputStream(" jdbc.properties " ); properties.load(inputStream); 文字列driver = properties.getProperty(" driver " ); 文字列url = properties.getProperty(" url " ); 文字列ユーザー名 = properties.getProperty( "username"); 文字列password = properties.getProperty( "password" ); System.out.println(ドライバー); System.out.println(url); System.out.println(username); System.out.println(password); inputStream。 close(); } @Test public void loader2()throws Exception { // 構成インスタンスを作成する Properties properties = new Properties(); // クラスローダーがファイルを読み取る場所デフォルトは、現在のモジュールまたはプロジェクトのsrcパッケージの下の InputStream です。のinputStream =ローダクラス .getClassLoader()getResourceAsStream( "jdbc.properties。" )。 // 加载 properties.load(inputStream); // 读取信息 String driver = properties.getProperty( "driver" ); 文字列url = properties.getProperty( "url" ); 文字列username = properties.getProperty( "username" ); 文字列password = properties.getProperty( "password" ); System.out.println(driver); System.out.println(url); System.out.println(username); System.out.println(password); inputStream.close(); } @Test 公共 ボイド loader3()スロー{例外 //はの構成例を作成 プロパティプロパティを= 新しい新しいプロパティ(); // 位置は、現在のパケットのSRCまたはプロジェクトのモジュールで20%、デフォルトのクラスローダをコードするファイル戻しURL読み 文字列のパス=ローダーを。クラス .getClassLoader ().getResource( "jdbc.properties" ).getFile(); // 文字列をデコードする必要があるdecode = URLDecoder.decode(path、 "UTF-8" ); // ストリームオブジェクトを作成する InputStream inputStream = new FileInputStream(decode); // 装填構成 は、Properties.load(のinputStream); @ 情報読み取るため の文字列ドライバ= properties.getProperty( "ドライバ"); 文字列url = properties.getProperty( "url" ); 文字列username = properties.getProperty( "username" ); 文字列password = properties.getProperty( "password" ); System.out.println(driver); System.out.println(url); System.out.println(username); System.out.println(password); inputStream.close(); } }
ランタイムクラスのオブジェクトを作成する
@Test 公共 ボイド getInstanceByReflect()スロー例外{ クラスの<person> = personClassのPerson。クラス; // このメソッドは、インスタンス作成するので、クラスのクラスインスタンスJDK9 +で直接オブジェクトを作成するためには推奨されない // .newInstanceを();内部コールを空の引数のコンストラクタには、空の引数のコンストラクタが例外たinvoke、存在しない、実行されている // 空の引数のコンストラクタを提供しなければならないランタイムクラスは、アクセス権が少ないデフォルトよりはならない // :空のパラメータのコンストラクタのためのJavaBean要求の理由 // このことにより、 Beanのインスタンスを作成するためにコンストラクターを呼び出すために反映 // サブクラスがランタイムクラスを継承する ときに、super()を呼び出して、親クラスにもこのコンストラクターがあることを確認します Person person = personClass.newInstance(); System.out.println(person); }
リフレクションの動的な性質、動的にサンプルを生成
@Test public void dynamic()はClassNotFoundException、IllegalAccessException、InstantiationExceptionをスローします{ for(int i = 0; i <100; i ++ ){ int random = new Random()。nextInt(3 ); String classPath = null ; スイッチ(ランダム){ ケース 0 : classPath = "java.util.Date" ; 休憩; ケース 1 : classPath= "java.lang.Object" ; 休憩; ケース 2 : classPath = "cn.dai.Reflection.Person" ; } クラス <?> name = Class.forName(classPath); オブジェクトインスタンス = name.newInstance(); System.out.println(instance); } }