コンピレーション期間中にクラスを取得することに関するさまざまな情報を提供することに加えて、Javaは、実行期間中にクラスに関するさまざまな情報をリフレクションで取得することもできます。リフレクションを通じてクラス情報を取得し、クラス情報を取得した後、次の関連コンテンツを取得できます。
この記事では、上記の側面からJavaの反射も紹介します。この記事に関係するすべてのコードが反映されています
まず、Javaクラスがリフレクションの研究オブジェクトとしてリリースされます。クラスの内容は次のとおりです。
public abstract class fatherobjectはrunnable {public void dosomething(){system.out.println( "do sonthing ..."); }} public class example objectはfatherobjectを拡張します{public int age = 30; public string name = "byhieg";プライベート整数スコア= 60; public void printname(){system.out.println(name); } public int getage(){return age; } public void Setage(int age){this.age = age; } public string getname(){return name; } public void setName(string name){this.name = name; } public Integer getScore(){return score; } public void setScore(整数スコア){this.score = score; } public example object(){} public example object(string name){} public example object(int age、integer score){} @override public void dosomething(){super.dosomething(); } @Override public void run(){system.out.println( "run ..."); }}クラスオブジェクト
当社のアプリケーションは、反射の知識ポイントを使用します。実行時にクラスの情報を取得し、クラスの情報に基づいて特定の操作を行う必要があります。次に、最初のことはクラスの情報を取得することであり、クラスの情報を保存するためにJDKにクラスオブジェクトが提供されます。したがって、反射の最初のステップは、クラスオブジェクトを取得することです。 JDKにクラスオブジェクトを取得するには、2つの方法があります。
1つ目は、コードを書くときにクラスの名前を知っている場合、次の方法でクラスオブジェクトを直接取得できることです。
Class exampleObjectClass = ExampleObject.class;
2番目のタイプは、コードを書くときにクラスの名前がわからないが、実行時にクラス名の文字列を取得でき、次の方法でクラスオブジェクトを取得できることです。
Class exampleObjectClass = Class.forName("cn.byhieg.reflectiontutorial.ExampleObject");
この方法には2つの条件が必要であることに注意してください。第一に、forNameの文字列は完全に適格な名前である必要があり、次に、クラスクラスはクラスパスのパスの下にある必要があります。このメソッドはClassNotFoundExceptionの例外をスローするためです。
このクラスオブジェクトを取得した後、クラスに関するさまざまな情報を取得できます。最初にいくつかの情報が言及されています。以下に、言及されていないクラスに関する情報について説明しましょう。
クラスの名前を取得します
クラスの名前を取得するには2つの方法があります。1つはgetName()で、もう1つはgetsimplename()です。最初の名前には完全な資格のある名前があり、2番目の名前はパッケージ名なしでこのクラスの名前を取得します。次の例をご覧ください。上記のコードで取得されたクラスオブジェクト。
string fullclassname = emblesObjectClass.getName(); string simpleclassname = emblesobjectclass.getSimplename(); System.out.println(FullClassName); system.out.println(simpleclassname); system.out.println(simpleclassname);
結果は次のとおりです。
cn.byhieg.ReflectionTutorial.exampleObjectExampleObject
クラス、親クラス、および実装インターフェイスのパッケージ名を取得します
クラスのパッケージ名と親クラスは、次のコードで取得できます。
//パッケージ情報パッケージApackage = exampleObjectClass.getPackage(); System.out.println(apackage); //親クラスを取得しましたsuperclass = emblesObjectClass.getSuperClass(); system.out.println(superclass.getSimplename());
結果は次のとおりです。
パッケージcn.byhieg.ReflectionTutorialFatherObject
明らかに、親クラスの返品値を取得することもクラスオブジェクトです。次に、このオブジェクトを使用して、親クラスが抽象クラスであるかどうかを判断するなど、親クラスに関する情報を取得できます。
System.out.println("父类是不是抽象类" + Modifier.isAbstract(superClass.getModifiers()));
GetModifiersはクラス修飾子を取得し、それによりクラス修飾子を取得できます。もちろん、このgetModifiersはクラスオブジェクトと呼ばれるだけでなく、メソッドオブジェクトを呼び出すことができます。
java.lang.reft.modifierクラスのメソッドを使用して、修飾子のタイプを確認できます。
modifier.isabstract(int modifiers); modifier.isfinal(int modifiers); modifier.isinterface(int modifiers); modifier.isnative(int modifiers); modifier.isprivate(int modifiers); modifier.isprotected(int modifiers); modififiers(int modifiers); modifier.isstic(int -modifiers(int modifiers); modifiers); modifier.isstrict(int modifiers); modifier.issynchronized(int modifiers); modifier.istransient(int modifiers); modifier.isvolatile(int modifiers);
さらに、親クラスによって実装されたインターフェイスを取得することもできます
// interface class [] classes = superclass.getInterfaces()を取得します。 System.out.println( "親クラスのインターフェイス" +クラス[0]);
Javaクラスは多くのインターフェイスを実装できるため、配列を使用しますが、実際に使用する場合は、最初に配列の長さを決定する必要があります。
以下に、上記のコンテンツの説明に焦点を当てます。
コンストラクタ
Java Reflectionを使用して、クラスコンストラクターを取得し、コンストラクターに基づいて実行時にオブジェクトを動的に作成できます。最初に、Javaは次のようなコンストラクターのインスタンスを取得します。
// constructorConstructor [] constructors = emblesObjectClass.getConstructors(); for(constructor constructor:constructors){system.out.println(constructor.tostring()); }結果は次のとおりです。
public cn.byhieg.ReflectionTutorial.exampleObject(int、java.lang.integer)public cn.byhieg.ReflectionTutorial.exampleObject(java.lang.string)public cn.byhieg.ReflectionTutorial.exampleObject()
事前にアクセスするコンストラクターのパラメータータイプを知っている場合は、次の方法を使用して、次のように指定されたコンストラクターを取得できます。
Constructor constructor = exampleObjectClass.getConstructor(String.Class); System.out.println(constructor.toString());
結果は明らかに次のとおりです。
public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String)
別のコンストラクターも次の方法で取得できます
Constructor constructor = exampleObjectClass.getConstructor(int.class、integer.class); System.out.println(constructor.toString());
さらに、コンストラクターのパラメーターがわからず、すべてのコンストラクターオブジェクトのみを取得できる場合、各コンストラクターが次のように使用するパラメーターを取得できます。
constructor [] constructors = emblesObjectClass.getConstructors(); for(constructor constructor:constructors){class [] parametertypes = constructor.getParametertypes(); System.out.println( "コンストラクターパラメーターはAsですフォロー================================================================================== ============================================================================== for(class clz:parametertypes){system.out.println( "parametertype" + clz.toString()}};結果は次のとおりです。
コンストラクターのパラメーターは次のとおりです==============================================================================================
ここでは、パラメーターレス構造方法が結果を印刷しないことがわかります。基本型のクラスオブジェクトと参照タイプのクラスオブジェクトは異なります。
これで、オブジェクトは、コンストラクターからのさまざまな情報に基づいて動的に作成できます。
オブジェクトオブジェクト= constructor.newinstance(1,100); system.out.println(object.toString());
オブジェクトを作成するための2つの条件があります。最初はパラメーターコンストラクターを介して作成されます。 2つ目は、コンストラクターオブジェクトをパラメーター情報に渡すGetConstructorを介して取得する必要があることです。
最初の条件は、パラメーター構築方法なしで作成できるオブジェクトの場合、コンストラクターオブジェクトを取得する必要がないことです。クラスオブジェクトはnewInstance()メソッドを呼び出し、オブジェクトを直接作成します。
2番目の条件は、exampleObjectClass.getConstructor(String.Class)の形式でコンストラクターオブジェクトを取得する必要があることです。 GetConstructorsを介してコンストラクターアレイを取得し、指定されたコンストラクターオブジェクトを呼び出してJDK1.8にオブジェクトを作成することは間違っています。しかし、JDK1.6は正常です。
変数
Java Reflectionを使用して、実行時にクラスの変数情報を取得でき、オブジェクトを作成して、上記の方法に従って変数値を設定できます。まず、すべてのパブリック変数は、次の方法に従うことによって取得されます。
field [] fields = emblesObjectClass.getFields(); for(field:fields){system.out.println( "変数は:" + field.toString()); }結果は次のとおりです。
変数は次のとおりです:public int cn.byhieg.ReflectionTutorial.exampleObject.age変数は次のとおりです。publicjava.lang.string cn.byhieg.reflectionTutorial.exampleObject.name
明らかに、取得したすべてのパブリック変数は公開されており、上記のプライベート変数スコアは取得されません。
コンストラクターが取得されるのと同じ方法で、パラメーター名を指定して、指定された変数を取得できます。
フィールドフィールド= exampleObjectClass.getField( "age"); system.out.println( "変数is:" + field.toString());
上記の変数のToStringメソッドによって得られた名前は長すぎます。 Javaは、クラスに記述された変数の名前を返すフィールドクラスにgetNameメソッドを提供します。上記のコードは、field.getName()に変更できます。
反射は、変数を取得する方法を提供するだけでなく、変数値を設定する方法も提供します。次の方法に従うことにより、動的に生成されたクラスの変数値を変更できます。
exampleObject object =((exampleObject)constructor1.newinstance( "byhieg")); System.out.println( "元の年齢は" + object.age); field.set(object、10); System.out.println( "変更後の年齢は" + object.age);
結果は次のとおりです。
元の年齢は30歳で、変化後の年齢は10です
上記のコードによると、Ageという名前のフィールドオブジェクトを取得し、オブジェクトの設定メソッドを呼び出し、オブジェクトと変更する値を渡してから、オブジェクトの値を変更できます。この方法は、メンバー変数だけでなく、静的変数にも役立つことに注意してください。もちろん、静的変数の場合、オブジェクトを渡さずにnullを渡すことは問題ありません。
方法
クラスのさまざまな情報を提供することに加えて、Java Reflectionはメソッド情報も提供します。反射により、メソッド名、メソッドパラメーター、メソッドリターンタイプ、および呼び出しメソッドを取得できます。
まず、次のコードを使用してメソッドを取得します。
//出力クラスのパブリックメソッド[] Methods = exampleObjectClass.getMethods(); for(method method:method){system.out.println( "method ="+ method.getname()); }変数を取得するように馴染みのあるコード。 GetNameはここで直接呼び出され、クラスでメソッド名を作成します。これを書いた後、Javaはパラメーターに基づいて特定の方法も提供していると自然に考える必要があります。
メソッドメソッド= exampleObjectClass.getMethod( "setage"、int.class); System.out.println(method.getName());
ここでの違いは、getMethodメソッドもパラメータータイプ情報を渡す必要があることです。メソッドパラメーターを取得する例は次のとおりです。
メソッドメソッド= exampleObjectClass.getMethod( "setage"、int.class); System.out.println(method.getName()); for(class clz:method.getParametertypes()){system.out.println( "method of method" + clz.getname()); }結果は次のとおりです。
セッジメソッドのパラメーターint
メソッドリターンタイプを取得する例は次のとおりです。
System.out.println(method.getReturnType().getName());
結果は次のとおりです。
void
さらに、Java Reflectionは、呼び出しを呼び出すことで得られた方法をサポートしています。例は次のとおりです。
method.invoke(exampleObjectClass.newInstance(),1);
最初のパラメーターの呼び出しはこのオブジェクトであり、2番目のパラメーターは可変長配列であり、メソッドのパラメーターは渡されます。フィールドオブジェクトのように、静的メソッドの場合、nullを渡して静的メソッドを呼び出すことができます。
プライベート変数とプライベートメソッド
上記の方法は、パブリックメソッドと変数のみを取得できますが、非公開の修正方法と変数を取得することはできません。 Javaは、非公開の変数と方法を取得するための追加の方法を提供します。つまり、私的変数と方法は、getDeclaredFieldsおよびgetDeclaredMethodsメソッドを通じて取得されます。また、指定された変数名とメソッド名を取得するために、getDeclaredField(変数名)とgetDeclaredMethod(メソッド名)の使用もサポートしています。ただし、この方法で取得したフィールドオブジェクトとメソッドオブジェクトは直接使用できません。これらのオブジェクトは、通常の使用のためにsetAccessable(true)と呼ばれる必要があります。次の方法は、上記と同じである可能性があります。
注釈
最初に注釈を含むクラスを書きます:
@myannotation(name = "byhieg"、value = "hello world")public class annotationobject {@myannotation(name = "field"、value = "variable")public string field; @myannotation(name = "method"、value = "method")public void dosomething(){system.out.println( "do montse"); } public void dootherthing(@myannotation(name = "param"、value = "param")string param){}}@retention(retentionpolicy.runtime)public @interface myannotation {public string name(); public string value();}Javaは、実行時にクラスの注釈の取得に関する情報を提供し、クラスの注釈、メソッドアノテーション、パラメーターアノテーション、可変注釈を取得できます。
上記の取得方法と同様に、Javaは2つの取得方法を提供します。 1つは、すべての注釈を取得して配列を返すことです。2つ目は、指定された注釈を指定することです。
次の2つの取得方法を説明するための例としてクラスの注釈を取りましょう。
クラスCLZ = AnnotationObject.Class; annotation [] annotations = clz.getAnnotations(); Annotation Annotation = clz.getAnnotation(annotationObject.class);
次に、取得した注釈に基づいて、後続の処理を実行できます。以下は処理の例です。
for(annotation annotation:annotations){if(annotation of myannotation){myannotation myannotation =(myannotation)annotation; System.out.println( "name:" + myannotation.name()); system.out.println( "value:" + myannotation.value()); }}上記のクラスの注釈は、クラスオブジェクトを使用してgetannotationsを呼び出すことによって取得されます。メソッドアノテーションと可変注釈は同じです。注釈を取得するために、メソッドオブジェクトとフィールドオブジェクトをそれぞれ使用してgetDeclaredAnnotationsに電話します。言うことはあまりありません。たとえば、反射コードを参照してください
パラメーターアノテーションは、比較的厄介なアイテムです。取得方法が比較されます。最初のステップは、最初にメソッドオブジェクトを取得し、getParameterAnnotationsを呼び出すことです。ただし、メソッドオブジェクトには多くのパラメーターがあり、各パラメーターには多くの注釈があるため、この戻り値は2次元配列です。例は次のとおりです。
メソッドmethod1 = clz.getmethod( "dootherthing"、string.class); annotation [] [] annotationinparam = method1.getParameterAnnotations(); class [] params = method1.getParametertypes(); int i = 0; for(annotation [] annotations:annotationinparam){class para = params [i ++]; for(annotation annotation:annotations){if(annotation of myannotation){myannotation myannotation =(myannotation)annotation; System.out.println( "param:" + para.getName()); System.out.println( "name:" + myannotation.name()); system.out.println( "value:" + myannotation.value()); }}}ジェネリック
Javaジェネリックは消去を通じて実装されるため、特定のパラメーター化されたタイプのジェネリックに関する情報を直接取得することは困難ですが、反射を使用して間接形式を介してジェネリック情報を取得できます。たとえば、次のクラス:
public class genericObject {public list <string> lists; public List <String> getLists(){return lists; } public void setlists(list <string> lists){this.lists = lists; }}メソッドが汎用クラスを返す場合、メソッドオブジェクトを介してgetGenericReturnTypeを呼び出してgetGenericReturnTypeを呼び出して、この汎用クラスの特定のパラメーター化タイプが何であるかを取得できます。次のコードを見てください。
class clz = genericobject.class;メソッドメソッド= clz.getMethod( "getLists");型Generictype = method.getGenericReturnType(); if(parameterizedTypeのgenerictypeインスタンス){parameterizedType parameterizedType =((parameterizedType)genericType); type []型= parameterizedType.getActualTypearguments(); for(typeタイプ:タイプ){class everityclz =((class)type); system.out.println( "パラメーター化タイプIS:" + eractclz); }}結果は次のとおりです。
参数化类型为: class java.lang.String
手順は少し面倒なので、次の説明は次のとおりです。
結果を調べることで、ジェネリックに関する具体的な情報を取得しました。
メソッドが汎用型を返す場合は、上記のクラスのセットリストメソッドなど、メソッドのパラメーターによって汎用タイプのパラメーター化されたタイプの汎用型を取得することもできます。例は次のとおりです。
メソッドsetMethod = clz.getMethod( "setLists"、list.class); type [] genericParametertypes = setMethod.getGenericParametertypes(); for(type genericparametertype:genericparametertypes){system.out.println( "genericparametertypes is:" + genericparametertype.getTypename()); if(parameterizedTypeのgenericparametertypeインスタンス){parameterizedType parameterizedType =((parameterizedType)genericParametertype); system.out.println( "parameterizedType is:" + parameterizedType.getTypename());タイプタイプ[] = parameterizedType.getActualTypearguments(); for(type type:types){system.out.println( "parameterized type is:" +((class)type).getname()); }}}実行結果は次のとおりです。
genericParametertypesは:java.util.list <java.lang.string> parameterizedtype is:java.util.list <java.lang.string> parameterized type is:java.lang.string
メソッドのパラメーターには複数の一般的なタイプがある可能性があるため、配列を取得するためにGenericParameterTypesを取得し、各要素にパラメーター化されたタイプがあるかどうかを判断する必要があります。後続の手順は上記の手順に似ているので、あまり言いません。
メソッドパラメーターにも汎用クラスが含まれていない場合、変数タイプ、つまりフィールドクラスが使用される最後のケースのみが残ります。例は次のとおりです。
フィールドフィールド= clz.getfield( "lists");型型= field.getGenerictype(); if(parameterizedTypeのタイプインスタンス){parameterizedType parameterizedType =((parameterizedType)type); type []型= parameterizedType.getActualTypearguments(); for(type type1:types){system.out.println( "parameterized type:" +((class)type1).getTypename()); }}原則は上記と同じですが、型オブジェクトはfield.getGenerictype()を介していることを除いて、残りの操作についてはあまり言いません。
これは、反射を通じてパラメーター化された型ジェネリックを取得するための紹介です。
配列
Java Reflectionは、配列の作成、配列内の値へのアクセス、配列のクラスオブジェクトの取得など、配列で動作できます。
それについて簡単に話しましょう。配列を作成し、配列内の値にアクセスしましょう。反射パッケージの下のアレイクラスを使用することです。
// 3 int [] intarray =(int [])array.newinstance(int.class、3)の長さでintタイプの配列を作成します。 //(int i = 0; i <intarray.length; i ++){array.set(intarray、i、i+2); } //反射の形式の配列、(int i = 0; i <intarray.length; i ++){system.out.println(array.get(intarray、i)); }上記は、配列を作成し、反射を使用して配列内の値にアクセスすることです。
配列を取得するクラスオブジェクトの場合、 int []。クラスを使用するか、class.fornameを使用するだけです。これは奇妙な書き込み方法です。
class clz = class.forname( "[i"); System.out.println(clz.getTypename());
結果は次のとおりです。
int[]
このforNameの文字列は、 [配列を表します。INTを表します。FLOATはF 、double is Dなどを表します。通常のオブジェクトの配列を取得する場合は、次の形式を使用します。
Class stringClz = Class.forName("[Ljava.lang.String;");
[それが配列であり、 Lの右側はクラス名、タイプの右側はaです。 ;
この方法では、配列のクラスオブジェクトを取得するには面倒です。
配列のクラスオブジェクトを取得した後、 GetComponentTypeを呼び出して配列メンバーのタイプ情報を取得するなど、その一意の方法の一部を呼び出すことができます。たとえば、INTアレイはメンバータイプであり、INTです。
System.out.println(clz.getComponentType().getTypeName());
結果はintです
要約します
今回は、反射のさまざまなアプリケーションがこれで終わり、将来的には詳細な知識の説明があるかもしれません。特定のコードについては、反射コードを見ることができます
SRCパッケージにはさまざまなクラスがあり、テストクラスではこれらのクラスへのアクセスです。
上記はこの記事のすべての内容です。この記事の内容が、すべての人の勉強や仕事に役立つことを願っています。また、wulin.comをもっとサポートしたいと思っています!