Javaの基本 - リフレクション機構

Javaリフレクション機構の研究と応用

Javaのリフレクション機構が提供する機能:

  1. 実行時において任意のオブジェクトの属するクラスを確認する
  2. 実行時において任意のクラスのインスタンスを生成する
  3. 実行時において任意のクラスのメンバーフィールドとメソッドを確認する
  4. 実行時においてジェネリック情報を取り扱う
  5. 実行時において任意のオブジェクトのメンバーフィールドとメソッドにアクセスする
  6. 実行時において注釈を処理する
  7. 動的プロキシを生成する

リフレクションに関連する主要なAPI

java.lang.Class;          // クラスを表す
java.lang.reflect.Method;  // クラスのメソッドを表す
java.lang.reflect.Field;   // クラスのメンバーフィールドを表す
java.lang.reflect.Constructor;// クラスのコンストラクターを表す
.......

リフレクションのメリットとデメリット

メリット
  1. Javaプログラムの柔軟性と拡張性を向上させ、耦合度を低減し、自適応能力を高める
  2. プログラムがクラスを事前にハードコーディングせずに、任意のクラスのオブジェクトを作成・制御できる
デメリット
  1. リフレクションの性能が低い。リフレクション機構は柔軟性や拡張性の要求が高いシステムフレームに主に使用される
  2. リフレクションはプログラムの内部ロジックを曖昧にし、可読性が低下する可能性がある

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);

}
}

タグ: リフレクション Java 動的プログラミング プライベートメンバーアクセス プロキシ生成

5月28日 10:13 投稿