java reflection tutorial with examples
このビデオチュートリアルでは、Reflectionとは何か、およびReflectionAPIを使用してそれを実装する方法について説明します。
Javaでのリフレクションは、実行時にプログラムの動作を検査および変更することです。
このリフレクションAPIを使用すると、実行時にクラス、コンストラクター、修飾子、フィールド、メソッド、およびインターフェースを検査できます。 例えば、 クラスの名前を取得することも、クラスのプライベートメンバーの詳細を取得することもできます。
全体を読む JAVAトレーニングシリーズ Javaの概念に関する詳細については。
これがJavaReflectionのビデオチュートリアルです。
学習内容:
Javaでのリフレクション
特定のクラスでは、コンパイル時にそのプロパティとメソッドを変更でき、非常に簡単に変更できることを認識しています。プロパティとメソッドが匿名であるか名前を持っているかにかかわらず、コンパイル時に自由に変更できます。
ただし、実行時にこれらのクラス、メソッド、またはフィールドをオンザフライで変更することはできません。言い換えると、特に未知のオブジェクトの場合、実行時にさまざまなプログラミングコンポーネントの動作を変更することは非常に困難です。
Javaプログラミング言語はと呼ばれる機能を提供します '反射' これにより、実行時にクラス、フィールド、またはメソッドの実行時の動作を変更できます。
したがって、反射は次のように定義できます。 「実行時に不明なオブジェクトの実行時の動作を検査および変更する手法。オブジェクトは、クラス、フィールド、またはメソッドにすることができます。」
Reflectionは、Javaが提供する「アプリケーションプログラミングインターフェイス」(API)です。
「反射」プロセスを以下に示します。
上記の表現では、未知のオブジェクトがあることがわかります。次に、このオブジェクトでReflectionAPIを使用します。その結果、実行時にこのオブジェクトの動作を変更できます。
したがって、オブジェクトの動作を変更する目的で、プログラムでReflectionAPIを使用できます。オブジェクトは、メソッド、インターフェース、クラスなどのようなものにすることができます。これらのオブジェクトを検査し、リフレクションAPIを使用して実行時に動作を変更します。
Javaでは、「java.lang」と「java.lang.reflect」は、リフレクション用のクラスを提供する2つのパッケージです。特別なクラス「java.lang.Class」は、クラスの動作を検査および変更できるメタデータを抽出するためのメソッドとプロパティを提供します。
上記のパッケージで提供されているReflectionAPIを使用して、実行時にクラスとそのメンバー(フィールド、メソッド、コンストラクターなどを含む)を変更します。 Reflection APIの際立った特徴は、クラスのプライベートデータメンバーまたはメソッドも操作できることです。
Reflection APIは、主に次の場所で使用されます。
- リフレクションは主に、デバッグツール、JUnit、およびフレームワークで使用され、実行時に動作を検査および変更します。
- IDE(統合開発環境) 例えば。 Eclipse IDE、NetBeansなど。
- テストツールなど。
- これは、アプリケーションにサードパーティライブラリがある場合、および使用可能なクラスとメソッドについて知りたい場合に使用されます。
JavaのリフレクションAPI
Reflection APIを使用すると、次のエンティティにリフレクションを実装できます。
- フィールド :Fieldクラスには、データ型(int、double、Stringなど)、アクセス修飾子(private、public、protectedなど)、名前(識別子)、値などの変数またはフィールドを宣言するために使用する情報があります。
- 方法 :Methodクラスは、メソッドのアクセス修飾子、メソッドの戻り値の型、メソッド名、メソッドのパラメーターの型、メソッドによって発生する例外の型などの情報を抽出するのに役立ちます。
- ビルダー :コンストラクタークラスは、コンストラクターアクセス修飾子、コンストラクター名、およびパラメータータイプを含むクラスコンストラクターに関する情報を提供します。
- 編集 :修飾子クラスは、特定のアクセス修飾子に関する情報を提供します。
上記のクラスはすべてjava.lang.reflectパッケージの一部です。次に、これらの各クラスについて説明し、プログラミング例を使用して、これらのクラスについての考察を示します。
まず、クラスjava.lang.Classから始めましょう。
java.lang.Classクラス
java.lang.Theクラスは、実行時にクラスとオブジェクトに関するすべての情報とデータを保持します。これは、リフレクションに使用されるメインクラスです。
クラスjava.lang.Classは以下を提供します。
- 実行時にクラスメタデータを取得するメソッド。
- 実行時にクラスの動作を検査および変更するメソッド。
java.lang.Classオブジェクトを作成します
次のいずれかのオプションを使用して、java.lang.Classのオブジェクトを作成できます。
5年間の経験のためのoracleplsqlインタビューの質問
#1).class拡張子
Classのオブジェクトを作成する最初のオプションは、.class拡張子を使用することです。
例えば、Testがクラスの場合、次のようにClassオブジェクトを作成できます。
Class obj_test = Test.class;
次に、obj_testを使用してリフレクションを実行できます。これは、このオブジェクトがクラスTestに関するすべての情報を持っているためです。
#2)forName()メソッド
forName()メソッドは、クラスの名前を引数として受け取り、Classオブジェクトを返します。
例えば、Testクラスのオブジェクトは、次のように作成できます。
class obj_test = Class.forName (“Test”);
#3)getClas()メソッド
getClass()メソッドは、クラスのオブジェクトを使用してjava.lang.Classオブジェクトを取得します。
例えば、次のコードを検討してください。
Test obj = new Test (); Class obj_test = obj.getClass ();
最初の行では、Testクラスのオブジェクトを作成しました。次に、このオブジェクトを使用して「getClass()」メソッドを呼び出し、java.lang.Classのオブジェクトobj_testを取得しました。
スーパークラスとアクセス修飾子を取得する
java.lang.classは、任意のクラスのスーパークラスを取得するために使用されるメソッド「getSuperClass()」を提供します。
同様に、クラスのアクセス修飾子を返すメソッドgetModifier()を提供します。
次の例は、getSuperClass()メソッドを示しています。
import java.lang.Class; import java.lang.reflect.*; //define Person interface interface Person { public void display(); } //declare class Student that implements Person class Student implements Person { //define interface method display public void display() { System.out.println('I am a Student'); } } class Main { public static void main(String() args) { try { // create an object of Student class Student s1 = new Student(); // get Class object using getClass() Class obj = s1.getClass(); // get the superclass of Student Class superClass = obj.getSuperclass(); System.out.println('Superclass of Student Class: ' + superClass.getName()); } catch(Exception e) { e.printStackTrace(); } } }
出力
上記のプログラミング例では、インターフェイスPersonは単独のメソッド「display()」で定義されています。次に、personインターフェースを実装するStudentクラスを定義します。 mainメソッドでは、getClass()メソッドを使用してClassオブジェクトを取得し、getSuperClass()メソッドを使用してStudentオブジェクトの親またはスーパークラスにアクセスします。
インターフェースを取得する
クラスがいくつかのインターフェースを実装している場合、java.lang.ClassのgetInterfaces()メソッドを使用してこれらのインターフェース名を取得できます。このために、Javaクラスでリフレクションを実行する必要があります。
以下のプログラミング例は、Java ReflectionでのgetInterfaces()メソッドの使用を示しています。。
import java.lang.Class; import java.lang.reflect.*; //define Interface Animals and PetAnimals interface Animals { public void display(); } interface PetAnimals { public void makeSound(); } //define a class Dog that implements above interfaces class Dog implements Animals, PetAnimals { //define interface method display public void display() { System.out.println('This is a PetAnimal::Dog'); } //define interface method makeSound public void makeSound() { System.out.println('Dog makes sound::Bark bark'); } } class Main { public static void main(String() args) { try { // create an object of Dog class Dog dog = new Dog(); // get class object Class obj = dog.getClass(); // get the interfaces implemented by Dog Class() objInterface = obj.getInterfaces(); System.out.println('Class Dog implements following interfaces:'); //print all the interfaces implemented by class Dog for(Class citem : objInterface) { System.out.println('Interface Name: ' + citem.getName()); } } catch(Exception e) { e.printStackTrace(); } } }
出力
上記のプログラムでは、AnimalsとPetAnimalsの2つのインターフェースを定義しました。次に、これら両方のインターフェイスを実装するクラスDogを定義します。
mainメソッドでは、java.lang.ClassのDogクラスのオブジェクトを取得して、リフレクションを実行します。次に、getInterfaces()メソッドを使用して、Dogクラスによって実装されているインターフェイスを取得します。
リフレクション:フィールド値を取得する
すでに述べたように、パッケージjava.lang.reflectは、クラスのフィールドまたはデータメンバーを反映するのに役立つFieldクラスを提供します。
以下にリストされているのは、フィールドのリフレクションのためにFieldクラスによって提供されるメソッドです。
方法 | 説明 |
---|---|
getField( 'fieldName') | 指定されたフィールド名を持つフィールド(パブリック)を返します。 |
getFields() | すべてのパブリックフィールド(クラスとスーパークラスの両方)を返します。 |
getDeclaredFields() | クラスのすべてのフィールドを取得します。 |
getModifier() | フィールドのアクセス修飾子の整数表現を返します。 |
set(classObject、value) | 指定された値をフィールドに割り当てます。 |
get(classObject) | フィールド値を取得します。 |
setAccessible(boolean) | trueを渡すことにより、プライベートフィールドにアクセスできるようにします。 |
getDeclaredField( 'fieldName') | 指定された名前のフィールドを返します。 |
以下に示すのは、公的および私的分野での反省を示す2つの反省の例です。
以下のJavaプログラムは、パブリックフィールドへの反映を示しています。
import java.lang.Class; import java.lang.reflect.*; class Student { public String StudentName; } class Main { public static void main(String() args) { try{ Student student = new Student(); // get an object of the class Class Class obj = student.getClass(); // provide field name and get the field info Field student_field = obj.getField('StudentName'); System.out.println('Details of StudentName class field:'); // set the value of field student_field.set(student, 'Lacey'); // get the access modifier of StudentName int mod1 = student_field.getModifiers(); String modifier1 = Modifier.toString(mod1); System.out.println('StudentName Modifier::' + modifier1); // get the value of field by converting in String String typeValue = (String)student_field.get(student); System.out.println('StudentName Value::' + typeValue); } catch(Exception e) { e.printStackTrace(); } } }
出力
このプログラムでは、パブリックフィールドStudentNameを持つクラス「Student」を宣言しました。次に、FieldクラスのAPIインターフェースを使用して、フィールドStudentNameでリフレクションを実行し、そのアクセス修飾子と値を取得します。
次のプログラムは、クラスのプライベートフィールドでリフレクションを実行します。プライベートフィールドに対して1つの追加の関数呼び出しが行われることを除いて、操作は似ています。プライベートフィールドに対してsetAccessible(true)を呼び出す必要があります。次に、パブリックフィールドと同様の方法でこのフィールドについてリフレクションを実行します。
import java.lang.Class; import java.lang.reflect.*; class Student { private String rollNo; } class Main { public static void main(String() args) { try { Student student = new Student(); // get the object for class Student in a Class. Class obj = student.getClass(); // access the private field Field field2 = obj.getDeclaredField('rollNo'); // make the private field accessible field2.setAccessible(true); // set the value of rollNo field2.set(student, '27'); System.out.println('Field Information of rollNo:'); // get the access modifier of rollNo int mod2 = field2.getModifiers(); String modifier2 = Modifier.toString(mod2); System.out.println('rollNo modifier::' + modifier2); // get the value of rollNo converting in String String rollNoValue = (String)field2.get(student); System.out.println('rollNo Value::' + rollNoValue); } catch(Exception e) { e.printStackTrace(); } } }
出力
リフレクション:方法
クラスのフィールドと同様に、クラスメソッドのリフレクションを実行し、実行時にそれらの動作を変更することもできます。このために、java.lang.reflectパッケージのMethodクラスを使用します。
以下にリストされているのは、クラスメソッドのリフレクションのためにメソッドクラスによって提供される関数です。
方法 | 説明 |
---|---|
getMethods() | クラスとそのスーパークラスで定義されているすべてのパブリックメソッドを取得します。 |
getDeclaredMethod() | クラスで宣言されたメソッドを返します。 |
getName() | メソッド名を返します。 |
getModifiers() | メソッドのアクセス修飾子の整数表現を返します。 |
getReturnType() | メソッドの戻り値の型を返します。 |
以下の例は、上記のAPIを使用したJavaでのクラスメソッドの反映を示しています。
import java.lang.Class; import java.lang.reflect.*; //declare a class Vehicle with four methods class Vehicle { public void display() { System.out.println('I am a Vehicle!!'); } protected void start() { System.out.println('Vehicle Started!!!'); } protected void stop() { System.out.println('Vehicle Stopped!!!'); } private void serviceVehicle() { System.out.println('Vehicle serviced!!'); } }class Main { public static void main(String() args) { try { Vehicle car = new Vehicle(); // create an object of Class Class obj = car.getClass(); // get all the methods using the getDeclaredMethod() in an array Method() methods = obj.getDeclaredMethods(); // for each method get method info for(Method m : methods) { System.out.println('Method Name: ' + m.getName()); // get the access modifier of methods int modifier = m.getModifiers(); System.out.print('Modifier: ' + Modifier.toString(modifier) + ' '); // get the return type of method System.out.print('Return Type: ' + m.getReturnType()); System.out.println('
'); } } catch(Exception e) { e.printStackTrace(); } } }
出力
上記のプログラムでは、メソッドgetDeclaredMethodsがクラスによって宣言されたメソッドの配列を返すことがわかります。次に、この配列を反復処理して、各メソッドの情報を表示します。
リフレクション:コンストラクター
java.lang.reflectパッケージの「Constructor」クラスを使用して、Javaクラスのコンストラクターを検査および変更できます。
コンストラクタークラスは、この目的のために次のメソッドを提供します。
方法 | 説明 |
---|---|
getConstructors() | クラスとそのスーパークラスで宣言されたすべてのコンストラクターを返します。 |
getDeclaredConstructor() | 宣言されたすべてのコンストラクターを返します。 |
getName() | コンストラクターの名前を取得します。 |
getModifiers() | コンストラクターのアクセス修飾子の整数表現を返します。 |
getParameterCount() | コンストラクターのパラメーターの総数を返します。 |
以下のリフレクションの例は、Javaでのクラスのコンストラクターのリフレクションを示しています。メソッドリフレクションと同様に、ここでもgetDeclaredConstructorsメソッドはクラスのコンストラクターの配列を返します。次に、このコンストラクター配列をトラバースして、各コンストラクターに関する情報を表示します。
import java.lang.Class; import java.lang.reflect.*; //declare a class Person with three constructors class Person { public Person() { } //constructor with no parameters public Person(String name) { } //constructor with 1 parameter private Person(String name, int age) {} //constructor with 2 parameters } class Main { public static void main(String() args) { try { Person person = new Person(); Class obj = person.getClass(); // get array of constructors in a class using getDeclaredConstructor() Constructor() constructors = obj.getDeclaredConstructors(); System.out.println('Constructors for Person Class:'); for(Constructor c : constructors) { // get names of constructors System.out.println('Constructor Name: ' + c.getName()); // get access modifier of constructors int modifier = c.getModifiers(); System.out.print ('Modifier: ' + Modifier.toString(modifier) + ' '); // get the number of parameters in constructors System.out.println('Parameters: ' + c.getParameterCount()); //if there are parameters, get parameter type of each parameter if(c.getParameterCount() > 0){ Class() paramList=c.getParameterTypes(); System.out.print ('Constructor parameter types :'); for (Class class1 : paramList) { System.out.print(class1.getName() +' '); } } System.out.println('
'); } } catch(Exception e) { e.printStackTrace(); } } }
出力
反射の欠点
リフレクションは強力ですが、無差別に使用しないでください。リフレクションを使用せずに操作できる場合は、使用を避けることが望ましいです。
以下にリストされているのは、Reflectionのいくつかの欠点です。
- パフォーマンスのオーバーヘッド: リフレクションは強力な機能ですが、リフレクティブ操作のパフォーマンスは非リフレクティブ操作よりも遅くなります。したがって、パフォーマンスが重要なアプリケーションでリフレクションを使用することは避けてください。
- セキュリティ制限: リフレクションはランタイム機能であるため、ランタイム権限が必要になる場合があります。したがって、制限されたセキュリティ設定でコードを実行する必要があるアプリケーションの場合、リフレクションは役に立たない可能性があります。
- 内部の露出: リフレクションを使用することで、クラス内のプライベートフィールドとメソッドにアクセスできます。したがって、リフレクションは抽象化を破り、コードを移植不可能にし、機能不全にする可能性があります。
よくある質問
Q#1)JavaでReflectionが使用されるのはなぜですか?
回答: リフレクションを使用すると、コンパイル時に匿名であっても、実行時にクラス、インターフェイス、コンストラクター、フィールド、およびメソッドを検査できます。この検査により、実行時にこれらのエンティティの動作を変更できます。
Q#2) Reflectionはどこで使用されますか?
回答: リフレクションは、ユーザー定義のクラスと相互運用するフレームワークの作成に使用されます。プログラマーは、クラスや他のエンティティが何であるかさえ知りません。
Q#3) Java Reflectionは遅いですか?
回答: はい、それは非リフレクションコードよりも遅いです。
Q#4) Java Reflectionは悪いですか?
回答: ある意味、そうです。まず第一に、コンパイル時の安全性が失われます。コンパイル時の安全性がないと、エンドユーザーに影響を与える可能性のある実行時エラーが発生する可能性があります。エラーのデバッグも困難になります。
Q#5) JavaでReflectionを停止するにはどうすればよいですか?
回答: 非リフレクション操作を記述することにより、リフレクションの使用を単純に回避します。あるいは、リフレクションを使用したカスタム検証などの一般的なメカニズムを使用できるかもしれません。
Javaリフレクションの詳細
java.lang.reflectパッケージには、リフレクションを実行するためのクラスとインターフェースがあります。また、java.lang.classは、リフレクションのエントリポイントとして使用できます。
クラスオブジェクトを取得する方法:
1.オブジェクトのインスタンスがある場合、
クラスc = obj.getclass();
2.クラスのタイプがわかっている場合は、
クラスc = type.getClass();
3.クラス名がわかっている場合は、
クラスc = Class.forName(“ com.demo.Mydemoclass”);
クラスのメンバーを取得する方法:
クラスメンバーは、フィールド(クラス変数)とメソッドです。
- getFields()– プライベートフィールドを除くすべてのフィールドを取得するために使用されます。
- getDeclaredField()– プライベートフィールドを取得するために使用されます。
- getDeclaredFields()– プライベートフィールドとパブリックフィールドを取得するために使用されます。
- getMethods() –プライベートメソッドを除くすべてのメソッドを取得するために使用されます。
- getDeclaredMethods() –パブリックメソッドとプライベートメソッドを取得するために使用されます。
デモプログラム:
ReflectionHelper.java:
これは、リフレクションAPIを使用して検査するクラスです。
ヤフー!メール最高のメールサービス
class ReflectionHelper { private int age; private String name; public String deptName; public int empID; 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 String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } }
ReflectionDemo.java
public class ReflectionDemo { public static void main(String() args) throws NoSuchFieldException, SecurityException { //get the class Class ReflectionHelperclass=ReflectionHelper.class; //get the name of the class String className = ReflectionHelperclass.getName(); System.out.println('className=='+className); System.out.println('getModifiers'+ReflectionHelperclass.getModifier s()); System.out.println('getSuperclass'+ReflectionHelperclass.getSupercla ss()); System.out.println('getPackage'+ReflectionHelperclass.getPackage()); Field() fields =ReflectionHelperclass.getFields(); //getting only the public fields for(Field oneField : fields) { Field field = ReflectionHelperclass.getField(oneField.getName()); String fieldname = field.getName(); System.out.println('only the public fieldnames:::::'+fieldname); } //getting all the fields of the class Field() privatefields =ReflectionHelperclass.getDeclaredFields(); for(Field onefield : privatefields) { Field field = ReflectionHelperclass.getDeclaredField(onefield.getName()); String fieldname = field.getName(); System.out.println('all the fieldnames in the class:::'+fieldname); } Method() methods =ReflectionHelperclass.getDeclaredMethods(); for(Method m: methods) { System.out.println('methods::::'+m.getName()); } }}
結論
このチュートリアルでは、JavaのReflectionAPIについて詳しく説明しました。クラス、インターフェイス、フィールド、メソッド、およびコンストラクターのリフレクションを実行する方法と、リフレクションのいくつかの欠点を見てきました。
リフレクションはJavaの比較的高度な機能ですが、言語に拠点を置くプログラマーが使用する必要があります。これは、注意して使用しないと、予期しないエラーや結果が発生する可能性があるためです。
リフレクションは強力ですが、慎重に使用する必要があります。それでも、リフレクションを使用すると、実行時までクラスやその他のエンティティを認識しないアプリケーションを開発できます。