Javaリフレクション機構の研究と応用
Javaのリフレクション機構が提供する機能:
- 実行時において任意のオブジェクトの属するクラスを確認する
- 実行時において任意のクラスのインスタンスを生成する
- 実行時において任意のクラスのメンバーフィールドとメソッドを確認する
- 実行時においてジェネリック情報を取り扱う
- 実行時において任意のオブジェクトのメンバーフィールドとメソッドにアクセスする
- 実行時において注釈を処理する
- 動的プロキシを生成する
リフレクションに関連する主要なAPI
java.lang.Class; // クラスを表す
java.lang.reflect.Method; // クラスのメソッドを表す
java.lang.reflect.Field; // クラスのメンバーフィールドを表す
java.lang.reflect.Constructor;// クラスのコンストラクターを表す
.......
リフレクションのメリットとデメリット
メリット
- Javaプログラムの柔軟性と拡張性を向上させ、耦合度を低減し、自適応能力を高める
- プログラムがクラスを事前にハードコーディングせずに、任意のクラスのオブジェクトを作成・制御できる
デメリット
- リフレクションの性能が低い。リフレクション機構は柔軟性や拡張性の要求が高いシステムフレームに主に使用される
- リフレクションはプログラムの内部ロジックを曖昧にし、可読性が低下する可能性がある
Studentクラス
package example_java_reflection;
public class Student {
private String name;
public int grade;
public Student() {
System.out.println("Student()...");
}
public Student(int grade) {
this.grade = grade;
}
private Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
public void show(){
System.out.println("こんにちは、私はStudentです");
}
private String showGrade(String grade){
return "私の学年は:"+grade;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", grade=" + grade +
'}';
}
}
テストクラス
package example_java_reflection;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestReflection {
/**
* リフレクションを使用する前の操作
*/
@Test
public void test1(){
// 1.Studentのインスタンスを作成
Student s1=new Student();
// 2.フィールドにアクセス
s1.grade=10;
System.out.println(s1.grade);
// メソッドを呼び出す
s1.show();
}
/**
* リフレクションを使用して上記の操作を行う
*/
@Test
public void test2() throws Exception {
// 1.Studentのインスタンスを作成
Class clazz=Student.class;
Student s1= (Student) clazz.newInstance();
System.out.println(s1);
// 2.フィールドにアクセス
Field gradeField=clazz.getField("grade");
gradeField.set(s1,10);
System.out.println(gradeField.get(s1));
// メソッドを呼び出す
Method showMethod=clazz.getMethod("show");
showMethod.invoke(s1);
}
/**
* Studentクラスのプライベートなメンバーに直接アクセスできないが、
* リフレクションを使用することでプライベートなメンバーにアクセスすることができる
*/
@Test
public void test3() throws Exception {
// プライベートコンストラクターを呼び出す
Class clazz=Student.class;
Constructor cons=clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Student s1=(Student)cons.newInstance("Tom",12);
System.out.println(s1);
// プライベートフィールドにアクセス
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(s1,"Jerry");
System.out.println(name.get(s1));
// プライベートメソッドを呼び出す
Method showGradeMethod=clazz.getDeclaredMethod("showGrade", String.class);
showGradeMethod.setAccessible(true);
String info= (String) showGradeMethod.invoke(s1,"CHN");
System.out.println(info);
}
}