Reflection ?
구체적인 클래스 타입을 알지 못해도 클래스의 메소드, 타입, 변수 들을 접근할 수 있도록 해주는 자바 API
Controller를 효율적인 구조로 만들기 위해 사용합니다.
JAVA API는 java.lang.reflect를 참고하시면 됩니다.
Command Pattern과 Reflection ?
Command Pattern
메서드로 의존하며 객체를 생성해 참조해서 사용
Reflection
package 정보를 String에 담아서 활용
클래스를 한층 더 정적으로 사용할 수 있음
Reflection으로 Class 객체를 생성
TestObj.class
package org.thinker.sample;
import org.thinker.sample.TestObj;
public class TestObj extends ParentObj {
static {
System.out.println("TestObj static block");
}
// static은 메모리 상에 올라가면서 main보다 먼저 실행된다
// 최초 한번만 실행된다
public TestObj() {
System.out.println("빈 생성자");
}
public TestObj(String str) {
System.out.println("문자열 생성자");
}
}
ReflectionTest2.class
package test;
import java.lang.reflect.Constructor;
public class ReflectionTest2 {
public static void main(String[] args) throws Exception{
String className = "org.thinker.sample.TestObj";
// org.thinker.sample = package명
// TestObj = Class명
Class clz = Class.forName(className);
// TestObj class의 정보를 clz에 담는다
// 이때 class의 static이 존재하며 최초 실행일 경우에 실행된다
Object obj = clz.newInstance();
// clz에 담긴 클래스를 객체로 생성해 obj에 담는다
// 생성자가 실행되며, static과는 다르게 매번 객체가 만들어질 때마다 생성자가 실행된다
System.out.println(obj);
// 생성자 오버로딩으로 경우의 수가 있을 때 Constructor클래스의 메서드에서 파라미터 타입을 넣어줌으로써 원하는 생성자를 가진 class 객체를 만들 수 있다
// Constructor con = clz.getDeclaredConstructor(String.class);
Constructor con = clz.getConstructor(String.class);
Object obj2 = con.newInstance("");
// 단, 이 경우 객체 생성 시 해당 타입의 파라미터값만을 넘겨줘야한다
System.out.println(obj2);
}
}
객체를 만들어낼 때 자신의 생성자를 통해 만들어낸다. 생성자를 만들어낼 때는 Constructor로 만들고, Constructor는 parameter를 맞추어야한다. 이 때 사용자 정의 생성자를 만들지 못하도록 하는 것이 가장 좋다.
생성자의 정보를 추출하는 방법
- getConstructor(parameter Types) : public으로 선언된 생성자에 접근 (단일 매개 변수 필요)
- getConstructor(new Class[]{parameter Types, parameter Types,... }) : public으로 선언된 생성자에 접근 (복합 매개 변수 필요)
- getDeclaredConstructor(parameterTypes) : 모든 생성자에 접근 (단일 매개 변수 필요)
- 단, SetAccessible(true) 필요