Reflection


Reflection


反射はJavaのAPIであり、ユーザーが特定のクラスタイプを知らずにクラスのメソッド、タイプ、変数にアクセスできるようにします.JVM上で実行されているアプリケーションのランタイム動作をチェックまたは変更する必要があるプログラムです.
アプリケーションが実行され、SpringでBeanFactoryからオブジェクトが呼び出されると、オブジェクトのインスタンスが作成されます.この場合、反射技術が使用されます.反射はフレームやライブラリでよく使用されます.ユーザがどのクラスを作成するかは予測できないため,反射を用いて動的に解決する.
サンプルを使用して、コードとともに表示します.
public class Car {
	private final String name;
    private int position;
    
    public Car(String name, int position) {
    	this.name = name;
        this.position = position;
    }
    
    public void move() {
    	this.position += 1;
    }
  	
    public int getPosition() {
    	return position;
   }
public static void main(String[] args) {
	Object obj = new Car("foo", 0); - (1)
    obj.move();	- (2)
}
Objectクラスはすべてのオブジェクトの親であるため,(1)とともに使用できる.サブオブジェクトCarをオブジェクトに割り当てています.でも(2)可能ですか?あり得ない.
Javaはコンパイラを使用します.コンパイル時間によってタイプが決まります.objという名前のオブジェクトはObjectタイプなので、Carのメソッドmoveが見つかりません.したがって、上記のコードでコンパイルエラーが発生します.
この場合、Reflection APIを使用することができる.
public static void main(String[] args) {
	Object obj = new Car("foo", 0);
	Class car = Car.class; - (3)
    Method move = car.getMethod("move");
    
    move.invoke(obj, null); - (4)
    
    Method getPosition = car.getMethod("getPosition");
    int position = (int)getPosition.invoke(obj, null);
    System.out.println(position);
(3)Reflection API(3つ目など)を使用して,クラス名のみでそのクラス,メソッド,作成者,フィールドに関する情報を取得する.
(4)invokeメソッドでメソッドを実行するオブジェクトとそのメソッドに渡されるパラメータを指定する.
反射は次の情報をもたらします.これにより、オブジェクトの作成、メソッドの呼び出し、変数値の変更が可能になります.
  • class
  • (1) 클래스 타입을 아는 경우
    Class class = Car.class;
    ※ primitive 타입일 경우
       Class class = boolean.class;
       Class class = Double.TYPE;
       Class class = Void.TYPE;
    (2) 클래스의 이름만 알고 있는 경우
    Class class = Car.forName("com.test.Car");
    
    
  • constructor
  • (1) 인자없는 생성자 리턴
    Constructor constructor = class.getDeclaredConstructor();
    (2) 인자가 String인 생성자 리턴
    Constructor constructor = class
    				.getDeclaredConstructor(String.class);
    (3) private, public 관계없이 모든 생성자 리턴
    Constructor constructor = class
    				.getDeclaredConstructors();
    (4) public 생성자만 리턴
    Constructor constructor = class.getConstructors();
  • Method
  • (1) 메소드 이름과 파라미터 정보와 일치하는 메소드 리턴
    Method method = class
    				.getDeclaredMethod("method", int.class);
    (2) 파라미터 정보 여러개인 경우
    Class types[] = new Class[2];
    types[0] = int.class;
    types[1] = boolean.class;
    Method method = class
    				.getDeclaredMethod("method", types);
    (3) 모든 메소드 리턴, Super 클래스 정보 제외
    Method method = class.getDeclaredMethods();
    (4) 모든 메소드 리턴, Super 클래스 포함
    Method method = class.getMethods();
    
    (5) 메소드 호출, 파라미터 : 호출객체와 인자 값
    method.invoke(class, 10);
    (6) static 메소드 호출
    method.invoke(null, 10);
  • Field
  • (1) 이름과 일치하는 필드 리턴
    Field field = class.getDeclaredField("field");
    (2) 모든 필드 리턴, Super 클래스 정보 제외
    Field field = class.getDeclaredFields();
    (3) 모든 필드 리턴, Super 클래스 정보 포함
    Field field = class.getFields();
    
    (4) 인자값 변경, 파라미터 : 호출객체와 바꾸려는 값
    field.set(class, "change value");
    (5) static 필드 정보 가져오거나 변경하기
    field.set(null, "change value);
    field.get(null);
    

    なぜ反射するのですか?


    JVMの実行後、javaコードはコンパイルされてバイトコードに変換され、静的領域に格納される.従って、反射APIとは、これらの情報を用いて静的領域を探索し、情報を取得することである.

    反射の欠点


    特定のクラスタイプが分からなくても、クラスのメソッド、フィールドなどにアクセスできますが、パフォーマンスオーバーヘッドがあります.
    JVMは、コンパイル時ではなく、実行時にタイプを動的に解析し、情報を取得するため、最適化できません.
    また,直接アクセスできないプライベートインスタンス変数,メソッドのアクセス性(setアクセス可能)は抽象を破壊する.
    [参照]https://tecoble.techcourse.co.kr/post/2020-07-16-reflection-api/
    [参照]https://codechacha.com/ko/reflection/
    [参照]https://medium.com/msolo021015/%EC%9E%90%EB%B0%94-reflection%EC%9D%B4%EB%9E%80-ee71caf7eec5