Java反射の詳細な説明
この記事では、まだ小さな例を使用して説明しています。なぜなら、ケース駆動型が最高だといつも感じているからです。そうでなければ、理論を読んだだけでも、それを読んだ後は理解できません。ただし、記事を読んだ後に理論を振り返り、よりよく理解することをお勧めします。
メインテキストは以下に始まります。
[ケース1]オブジェクトを介して完全なパッケージとクラス名を取得します
パッケージ反射。 /***オブジェクトを介して完全なパッケージ名とクラス名を取得**/class demo {//その他のコード...} class hello {public static void main(string [] args){demo demo = new demo(); System.out.println(demo.getClass()。getName()); }}runningランニング結果】:refrict.demo
文を追加:クラスのすべてのオブジェクトは、実際にはクラスのインスタンスです。
Case 2】クラスオブジェクトをインスタンス化します
パッケージリフレクト; class demo {//その他のコード...} class hello {public static void main(string [] args){class <?> demo1 = null;クラス<?> demo2 = null;クラス<?> demo3 = null; try {//通常、このフォームを使用してみてくださいdemo1 = class.forname( "refrect.demo"); } catch(Exception e){e.printstacktrace(); } demo2 = new demo()。getClass(); demo3 = demo.class; System.out.println( "class name"+demo1.getName()); System.out.println( "class name"+demo2.getName()); System.out.println( "class name"+demo3.getname()); }}【操作結果】:
クラスnamereflect.demo
クラスnamereflect.demo
クラスnamereflect.demo
[ケース3]クラスを通じて他のクラスのオブジェクトをインスタンス化します
ノンパラメーターを構築してインスタンス化されたオブジェクト
パッケージ反射。 class person {public string getname(){return name; } public void setName(string name){this.name = name; } public int getage(){return age; } public void Setage(int age){this.age = age; } @Override public String toString(){return "["+this.name+""+this.age+"]"; }プライベート文字列名;プライベートインクエイジ; } class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } per per = null; try {per =(person)demo.newinstance(); } catch(instantiationexception e){// todo auto-fenated catch block e.printstacktrace(); } catch(Illegalaccessexception e){// todo auto-enerated catch block e.printstacktrace(); } per.setName( "Rollen"); per.Setage(20); system.out.println(per); }}【操作結果】:
[Rollen 20]
ただし、たとえば、パラメーターを持つ1つのコンストラクターのみを定義した後、デフォルトのパラメーターレスコンストラクターを直接キャンセルすると、エラーが発生します。
たとえば、コンストラクターを定義しました。
パブリックパーソン(文字列名、int age){this.age = age; this.name = name; }次に、上記のプログラムを実行し続けると、表示されます。
java.lang.instantiationexception:refrect.person
java.lang.class.newinstance0(class.java:340)
java.lang.class.newinstance(class.java:308)
at Refrom.hello.main(hello.java:39)
スレッド「Main」Java.lang.NullPointerExceptionの例外
at Refrom.hello.main(hello.java:47)
したがって、クラスを使用して他のクラスをインスタンス化するオブジェクトを作成する場合、パラメーターなしで独自のコンストラクターを定義する必要があります。
[ケース]クラスを通じて他のクラスのコンストラクターを呼び出します(この方法でクラスを通じて他のクラスのオブジェクトを作成することもできます)
パッケージ反射。 java.lang.reflt.constructorをインポートします。 class person {public person(){} public person(string name){this.name = name; } public Person(int age){this.age = age; } public Person(string name、int age){this.age = age; this.name = name; } public string getname(){return name; } public int getage(){return age; } @Override public String toString(){return "["+this.name+""+this.age+"]"; }プライベート文字列名; private int age;} class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); }人per1 = null; per2 = null;人per3 = null;人per4 = null; //すべてのコンストラクターを取得constructor <?> cons [] = demo.getConstructors(); try {per1 =(person)cons [0] .newinstance(); per2 =(person)cons [1] .newinstance( "Rollen"); per3 =(person)cons [2] .newinstance(20); per4 =(person)cons [3] .newinstance( "Rollen"、20); } catch(Exception e){e.printstacktrace(); } system.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println(per4); }}【操作結果】:
[null 0]
[Rollen 0]
[null20]
[Rollen 20]
【場合】
クラスによって実装されたインターフェイスを返します。
パッケージ反射。インターフェイス中国{public static final string name = "Rollen"; public static int age = 20; public void sayschina(); public void sayshello(string name、int age);}クラスの人は中国{public person(){} public person(string sex){this.sex = sex; } public string getSex(){return sex; } public void setSex(string sex){this.sex = sex; } @Override public void saychina(){system.out.println( "hello、china"); } @Override public void sayshello(string name、int age){system.out.println(name+""+age); } private string sex;} class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } //すべてのインターフェイスクラス<?> intes [] = demo.getInterfaces()を保存します。 for(int i = 0; i <intes.length; i ++){system.out.println( "実装インターフェイス"+intes [i] .getname()); }}}【操作結果】:
実装されたインターフェイスReflect.china
(次の例では、この例の人クラスを使用するため、スペースを節約するために、ここでは人コードパーツを貼り付けなく、メインクラスのコードのみが貼り付けられなくなります)
【ケース】:他のクラスで親クラスを取得します
class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } //親クラスを取得<?> temp = demo.getsuperclass(); System.out.println( "継承された親クラスは次のとおりです。"+temp.getName()); }}ランニング結果】
継承された親クラスは、java.lang.objectです
【ケース】:他のクラスのすべてのコンストラクターを取得します
この例では、プログラムの開始時に、java.lang.reflect。*インポートを追加する必要があります。
次に、メインクラスを次のように書きます。
class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } constructor <?> cons [] = demo.getConstructors(); for(int i = 0; i <cons.length; i ++){system.out.println( "constructor:"+cons [i]); }}}【操作結果】:
構築方法:public Reflect.person()
コンストラクター:public Reflect.person(java.lang.string)
しかし、注意深い読者は、上記のコンストラクターにはパブリックやプライベートなどの修飾子がないことがわかります
次の例で修飾子を取得しましょう
class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } constructor <?> cons [] = demo.getConstructors(); for(int i = 0; i <cons.length; i ++){class <?> p [] = cons [i] .getParametertypes(); system.out.print( "constructor:"); int mo = cons [i] .getModifiers(); system.out.print(modifier.toString(mo)+""); system.out.print(cons [i] .getname()); system.out.print( "("); for(int j = 0; j <p.length; ++ j){system.out.print(p [j] .getname()+"arg"+i); if(j <p.length-1){j <p.length-1){j <p.length-1){j <p.lengty-1){system.out.print( "、");}}} system.out.out.out.out.out; }}【操作結果】:
コンストラクター:public Reflect.person(){}
コンストラクター:public Reflect.person(java.lang.string arg1){}
方法に例外がある場合があります。見てみましょう:
class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } method method [] = demo.getMethods(); for(int i = 0; i <method.length; ++ i){class <?> returnType = method [i] .getRunType(); class <?> para [] = method [i] .getParametertypes(); int temp = method [i] .getModifiers(); system.out.print(modifier.tostring(temp)+""); System.out.print(returnType.getName()+""); system.out.print(method [i] .getname()+""); System.out.print( "("); for(int j = 0; j <para.length; ++ j){system.out.print(para [j] .getname()+""+"arg"+j); if(j <para.out.print( "、"、 ");}} class <? if(exce.length> 0){system.out.print( ")throws"); for(int k = 0; k <exce.length; ++ k){system.out.print(exce [k] .getname()+""); if(k <exce.length-1){system.out.print( "、"); }}} else {system.out.print( ")"); } system.out.println(); }}}【操作結果】:
public java.lang.string getSex()
public void setsex(java.lang.string arg0)
public void sayschina()
public void sayshello(java.lang.string arg0、int arg1)
パブリックファイナルネイティブVoid wait(long arg0)はJava.lang.interrupdedexceptionをスローします
Public Final void wait()throws java.lang.interrupdedexception
パブリックファイナルボイドウェイ(Long Arg0、int arg1)がJava.lang.interrupdedexceptionをスローします
public boolean equals(java.lang.object arg0)
public java.lang.String toString()
パブリックネイティブint hashcode()
パブリックファイナルネイティブjava.lang.class getClass()
パブリックファイナルネイティブvoid notify()
パブリックファイナルネイティブvoid notifyall()
[ケース]次に、他のクラスのすべてのプロパティを取得しましょう。最後に、クラスを通じてクラスのフレームワーク全体を取得するために、それらを一緒に整理します。
class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } System.out.println( "================================================================================= ============================================================================================================================================== ============================================================================================================================================== ====================================================================================================================================== Permission Modifier int mo = field [i]; System.out.println( "================================================================================ ============================================================================================================================================== ============================================================================================================================================ ============================================================================================================================================== filed1 = demo.getfields(); for(int j = 0; j <filed1.length; j ++){// permission modifier int mo = filed1 [j] .getModifiers(); string priv = modifier.toString(MO); //プロパティタイプクラス<?> type = filed1 [j] .getType(); System.out.println(priv + "" + type.getName() + "" + filed1 [j] .getName() + ";"); }}}【操作結果】:
===========================================================
プライベートJava.lang.String Sex;
==================================================================
public static final java.lang.String名;
パブリック静的最終int年齢。
[ケース]実際、他のクラスの方法は、反射を通じて呼び出すこともできます。
class hello {public static void main(string [] args){class <?> demo = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } try {//人クラスのsaychinaメソッドを呼び出す方法= demo.getmethod( "saychina"); method.invoke(demo.newinstance()); //人のsayhello method = demo.getMethod( "sayhello"、string.class、int.class); Method.Invoke(demo.newinstance()、 "Rollen"、20); } catch(Exception e){e.printstacktrace(); }}}【操作結果】:
こんにちは、中国
ローレン20
CASE CASE SETを呼び出して、他のクラスのメソッドを取得します
class hello {public static void main(string [] args){class <?> demo = null;オブジェクトobj = null; try {demo = class.forname( "refrect.person"); } catch(Exception e){e.printstacktrace(); } try {obj = demo.newinstance(); } catch(Exception e){e.printstacktrace(); } setter(obj、 "sex"、 "male"、string.class); getter(obj、 "sex"); } / ** * @param obj *操作のオブジェクト * @param att *操作の属性 * * / public static void getter(object obj、string att){try {method method = obj.getclass()。getMethod( "get" + att); system.out.println(method.invoke(obj)); } catch(Exception e){e.printstacktrace(); }} / ** * @param obj *操作のオブジェクト * @param att *操作の属性 * @param値 * @param type *パラメーターの属性 * * / public static void setter(object obj、string att、object value、class <?> type){try {method method = obj.getclass(); method.invoke(obj、value); } catch(Exception e){e.printstacktrace(); }}} // end class【操作結果】:
男
【ケース】反射による操作
class hello {public static void main(string [] args)スロー例外{class <?> demo = null;オブジェクトobj = null; demo = class.forname( "refrect.person"); obj = demo.newinstance();フィールドフィールド= demo.getDeclaredfield( "sex"); field.setAccessible(true); field.set(obj、 "male"); System.out.println(field.get(obj)); }} // end class[ケース]反射を通じて配列の情報を取得して変更します。
Import Java.lang.Reflect。*; class hello {public static void main(string [] args){int [] temp = {1,2,3,4,5}; class <? System.out.println( "array type:"+demo.getName()); system.out.println( "array length"+array.getLength(temp)); system.out.println( "配列の最初の要素:"+array.get(temp、0)); array.set(temp、0、100); System.out.println( "配列の最初の要素を変更した後、"+array.get(temp、0)); }}【操作結果】:
配列タイプ:int
配列長5
配列の最初の要素:1
変更後、配列の最初の要素は次のとおりです。
【ケースreflection反射を介して配列のサイズを変更します
class hello {public static void main(string [] args){int [] temp = {1,2,3,5,6,7,8,9}; int [] newtemp =(int [])arrayinc(temp、15); print(newtemp); System.out.println( "================================================================================================================= ========================================================================================= string [])Arrayinc(ATR、STR1); System.ArrayCopy(0、NewARR) array.getLength(obj);【操作結果】:
配列の長さは次のとおりです
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 ==============================================================================
配列の長さは次のとおりです
ABC NULL NULL NULL NULL NULL
動的エージェント
[ケース]最初に、クラスローダーを取得する方法を見てみましょう。
class test {} class hello {public static void main(string [] args){test t = new test(); system.out.println( "classloader"+t.getClass()。getClassLoader()。getClass()。getName()); }}【プログラム出力】:
クラスローダーsun.misc.launcher $ appclassloader
実際、Javaには3種類のクラスローダーがあります。
1)ブートストラップクラスローダーこのローダーはC ++で記述されており、一般的な開発ではめったに見られません。
2)拡張クラスローダーは、一般にJRE/LIB/EXTディレクトリのクラスに対応する拡張クラスのロードに使用されます
3)AppClassLoader ClassPathで指定されたクラスをロードし、最も一般的に使用されるローダーです。また、Javaのデフォルトローダーです。
動的プロキシを完了する場合は、最初にInvocationHandlerインターフェイスのサブクラスを定義する必要があり、プロキシの特定の操作が完了しました。
パッケージ反射; Import Java.lang.Reflect。*; //プロジェクトインターフェイスインターフェイス件名を定義{public string says(string name、int age);} // real Project class realsubject empments件名{@Override public string(string name、int age){return name + "" + age; }} class myInvocationHandlerを実装するrivocationhandler {private object obj = null;パブリックオブジェクトバインド(オブジェクトobj){this.obj = obj; proxy.newproxyinstance(obj.getClass()。getClassLoader()、obj .getClass()。getInterfaces()、this); } @OverrideパブリックオブジェクトInvoke(Object Proxy、Method Method、Object [] args)Throws throwable {object temp = method.invoke(this.obj、args); return temp; }} class hello {public static void main(string [] args){myInvocationHandler demo = new MyInvocationHandler();件名sub =(subject)demo.bind(new realSubject());文字列info = sub.say( "rolen"、20); System.out.println(info); }}【操作結果】:
ローレン20
クラスのライフサイクル
クラスが編集された後、次のステップはクラスの使用を開始することです。クラスを使用したい場合は、JVMとは間違いなく切り離せません。プログラムの実行中、JVMは、これらの3つのステップで完了します:ロード、リンク、および初期化。
クラスの読み込みは、クラスローダーを介して行われます。ローダーは.classファイルのバイナリファイルをJVMメソッド領域にロードし、ヒープ領域のこのクラスを記述するJava.lang.classオブジェクトを作成します。データをカプセル化するために使用されます。しかし、同じクラスは以前にクラスローダーによってのみロードされます
リンクは、バイナリデータを実行できる状態に組み立てることです。
リンクは、検証、準備、解析の3つの段階に分かれています
検証は、一般に、このバイナリファイルが現在のJVM(バージョン)に適しているかどうかを確認するために使用されます。
準備は、静的メンバーにメモリスペースを割り当てることです。デフォルト値を設定します
解析とは、すべてのシンボリック参照を実行中のプログラムで使用できるまで、定数プールのコードを直接参照として変換するプロセスを指します(完全な対応を確立します)
完了後、タイプは初期化されます。初期化後、クラスのオブジェクトは正常に使用できます。オブジェクトが使用されなくなった後、ゴミ収集されます。無料のスペースを解放します。
クラスオブジェクトを参照することがない場合、それはアンインストールされ、クラスのライフサイクルが終了します
工場モードには反射を使用します
リフレクションが必要ない場合は、工場モードを見てみましょう。
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
/ *** @author rollen-holtデザインパターンのモード}} class orange emplesient fruit {public void eat(){system.out.println( "orange"); }} //ファクトリークラスを構築する//言い換えれば、将来のクラス工場に他のインスタンスを追加するときに工場クラスを変更するだけが必要な場合{public static Fruit getInstance(string fruitname){fruit f = null; if( "apple" .equals(fruitname)){f = new Apple(); } if( "orange" .equals(fruitname)){f = new Orange(); } furne f; }} class hello {public static void main(string [] a){furt f = factory.getInstance( "orange"); f.eat(); }}このようにして、サブクラスを追加するときは、工場のクラスを変更する必要があります。サブクラスが多すぎると、大きく変わります。
それでは、反射メカニズムの使用を見てみましょう。
パッケージ反射。インターフェイスフルーツ{public abstract void eat();}クラスのアップルはフルーツを実装します{public void eat(){system.out.println( "apple"); }} class orange emplesient fruit {public void eat(){system.out.println( "orange"); }} class Factory {public static Fruit getInstance(string className){fruit f = null; try {f =(fruit)class.forname(classname).newinstance(); } catch(Exception e){e.printstacktrace(); } furne f; }} class hello {public static void main(string [] a){furt f = factory.getInstance( "reflect.apple"); if(f!= null){f.eat(); }}}これで、サブクラスを多く追加しても、工場クラスを変更する必要はありません。
上記の愛はリフレクションを通じてインターフェイスのインスタンスを取得することができますが、完全なパッケージとクラス名を渡す必要があります。さらに、ユーザーはインターフェイスで使用できるサブクラスの数を知ることができないため、属性ファイルの形式で必要なサブクラスを構成します。
見てみましょう:属性ファイルを組み合わせたファクトリーモード
最初にfurt.propertiesリソースファイルを作成します。
内容は次のとおりです。
Apple = rifflect.Apple
Orange = reflect.Orange
次に、メインクラスコードを書きます。
パッケージ反射。 java.io。*;インポートJava.util。*;インターフェイスフルーツ{public abstract void eat();}クラスのアップルはフルーツを実装します{public void eat(){system.out.println( "apple"); }} class orange emplesient fruit {public void eat(){system.out.println( "orange"); }} //操作プロパティファイルクラスinit {public staticプロパティgetPro()throws filenotFoundException、ioException {Properties pro = new Properties();ファイルf = new file( "Fruit.Properties"); if(f.exists()){pro.load(new fileinputStream(f)); } else {pro.setProperty( "apple"、 "refrect.apple"); pro.setProperty( "orange"、 "refrect.orange"); pro.Store(new FileOutputStream(f)、 "Fruit Class"); } return pro; }} class Factory {public static Fruit getInstance(string className){fruit f = null; try {f =(fruit)class.forname(classname).newinstance(); } catch(Exception e){e.printstacktrace(); } furne f; }} class hello {public static void main(string [] a)throws filenotfoundexception、ioexception {properties pro = init.getPro();フルーツF = Factory.getInstance(pro.getProperty( "Apple")); if(f!= null){f.eat(); }}}run run result】:Apple
上記は、Java反射メカニズムの詳細な説明です。今後も関連情報を追加し続けます。このサイトへのご支援ありがとうございます!