Java 리플렉션은 런타임에 클래스의 모든 능력을 분석하고 수정하는 과정입니다. Java Reflection API는 클래스와 그 멤버(필드, 메서드, 생성자 등)를 런타임에 조작하는 데 사용됩니다.
Java 리플렉션 API의 한 가지 장점은 클래스의 private 멤버도 조작할 수 있다는 것입니다.
java.lang.reflect 패키지는 리플렉션을 구현하기 위한 많은 클래스를 제공합니다. java.lang.Class 클래스의 메서드는 특정 클래스의 완전한 메타데이터를 수집하는 데 사용됩니다.
이 튜토리얼에서 배울 내용:
리플렉션이란
java.lang.reflect 패키지의 클래스들
java.lang.Class에서 사용되는 메서드들
클래스에 대한 완전한 정보 얻는 방법
예제 1: 클래스 메타데이터 얻기
예제 2: 변수 메타데이터 얻기
예제 3: 메서드 메타데이터 얻기
예제 4: 생성자 메타데이터 얻기
java.lang.reflect 패키지의 클래스들
다음은 리플렉션 구현을 위한 java.lang.reflect 패키지의 다양한 Java 클래스들입니다:
Field: 변수의 데이터 타입, 접근 제어자, 이름, 값 등 선언적 정보 수집
Method: 메서드의 접근 제어자, 반환 타입, 이름, 매개변수 타입, 예외 타입 등 선언적 정보 수집
Constructor: 생성자의 접근 제어자, 이름, 매개변수 타입 등 선언적 정보 수집
Modifier: 특정 접근 제어자에 대한 정보 수집
java.lang.Class에서 사용되는 메서드들
Public String getName(): 클래스 이름 반환
public Class getSuperclass(): 슈퍼클래스 참조 반환
Public Class[] getInterfaces(): 지정된 클래스가 구현한 인터페이스 배열 반환
Public int getModifiers(): 지정된 클래스의 수정자를 나타내는 정수 값 반환, "public static String toString(int i)" 메서드에 매개변수로 전달하여 주어진 클래스의 접근 지정자 반환
클래스에 대한 완전한 정보 얻기
클래스의 변수, 메서드, 생성자에 대한 정보를 얻으려면 클래스 객체를 생성해야 합니다.
public class Guru99ClassObjectCreation {
public static void main (String[] args) throws ClassNotFoundException {
// 1 - Class.forName() 메서드 사용
Class c1 = Class.forName("Guru99ClassObjectCreation");
// 2 - getClass() 메서드 사용
Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
Class c2 = guru99Obj.getClass();
// 3 - .class 사용
Class c3 = Guru99ClassObjectCreation.class;
}
}
"class" 클래스 객체 생성하는 다양한 방법:
예제 1: 클래스 메타데이터 얻기
다음 예제는 클래스 이름, 슈퍼클래스 이름, 구현된 인터페이스, 클래스의 접근 제어자 등 메타데이터를 얻는 방법을 보여줍니다.
아래 Guru99Base.class라는 클래스의 메타데이터를 얻겠습니다:
import java.io.Serializable;
public abstract class Guru99Base implements Serializable,Cloneable {
}
클래스 이름: Guru99Base
접근 제어자: public, abstract
구현된 인터페이스: Serializable, Cloneable
명시적으로 클래스를 확장하지 않았으므로 슈퍼클래스: java.lang.Object
아래 클래스는 Guru99Base.class의 메타데이터를 얻고 출력합니다:
import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
public static void main (String [] args) throws ClassNotFoundException {
// Guru99Base.class의 Class 객체 생성
Class<Guru99Base> guru99ClassObj = Guru99Base.class;
// 클래스 이름 출력
System.out.println("Name of the class is : " + guru99ClassObj.getName());
// 슈퍼클래스 이름 출력
System.out.println("Name of the super class is : " + guru99ClassObj.getSuperclass().getName());
// getInterfaces() 메서드로 구현된 인터페이스 목록을 Class 배열로 얻기
Class[] guru99InterfaceList = guru99ClassObj.getInterfaces();
// foreach 루프로 구현된 인터페이스 출력
System.out.print("Implemented interfaces are : ");
for (Class guru99class1 : guru99InterfaceList) {
System.out.print(guru99class1.getName() + " ");
}
System.out.println();
// getModifiers()와 Modifier.toString()으로 접근 제어자 얻기
int guru99AccessModifier = guru99ClassObj.getModifiers();
// 접근 제어자 출력
System.out.println("Access modifiers of the class are : " + Modifier.toString(guru99AccessModifier));
}
}
getName 메서드로 클래스 이름 출력
getSuperClass().getName()으로 슈퍼클래스 이름 출력
구현된 인터페이스 이름 출력
클래스가 사용한 접근 제어자 출력
예제 2: 변수 메타데이터 얻기
다음 예제는 변수 메타데이터를 얻는 방법을 보여줍니다:
여기에 몇 개의 변수를 가진 Guru99VariableMetaData.class라는 클래스를 만듭니다:
package guru;
public class Guru99VariableMetaData {
public static int guru99IntVar1=1111;
static int guru99IntVar2=2222;
static String guru99StringVar1="guru99.com";
static String guru99StringVar2="Learning Reflection API";
}
위 클래스의 변수 메타데이터 얻는 단계:
위 클래스의 클래스 객체 생성:
Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
Class guru99ClassObjVar = guru99ClassVar.getClass();
getFields() 또는 getDeclaredFields() 메서드로 필드 배열 형태의 메타데이터 얻기:
getMethods()는 지정된 클래스와 슈퍼클래스의 public 메서드 메타데이터 반환.
getDeclaredMethods()는 지정된 클래스의 모든 메서드 메타데이터만 반환.
getName() 메서드로 메서드 이름 얻기
getReturnType() 메서드로 메서드 반환 타입 얻기
getModifiers()와 Modifier.toString(int i)로 메서드 접근 제어자 얻기
getParameterTypes()로 메서드 매개변수 타입 얻기 (Class 배열 반환)
getExceptionTypes()로 던져지는 예외 얻기 (Class 배열 반환)
여기서 Guru99MethodMetaData.class에 있는 메서드들의 메타데이터를 얻는 클래스를 작성합니다:
package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Guru99MethodMetaDataTest {
public static void main (String[] args) {
// Guru99MethodMetaData.class의 Class 객체 생성
Class guru99ClassObj = Guru99MethodMetaData.class;
// getDeclaredMethods()로 클래스의 모든 메서드 메타데이터 얻기
Method[] guru99Methods = guru99ClassObj.getDeclaredMethods();
for(Method method : guru99Methods) {
// 메서드 이름 출력
System.out.println("Name of the method : " + method.getName());
// 메서드 반환 타입 출력
System.out.println("Return type of the method : " + method.getReturnType());
// 접근 제어자 리스트 얻고 출력
int guru99ModifierList = method.getModifiers();
System.out.println("Method access modifiers : " + Modifier.toString(guru99ModifierList));
// 메서드 매개변수 얻고 출력
Class[] guru99ParamList = method.getParameterTypes();
System.out.print("Method parameter types : ");
for (Class class1 : guru99ParamList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
// 메서드가 던지는 예외 얻고 출력
Class[] guru99ExceptionList = method.getExceptionTypes();
System.out.print("Exception thrown by method : ");
for (Class class1 : guru99ExceptionList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ");
}
}
}
Guru99MethodMetaData.class의 클래스 객체 생성
Method 배열로 모든 메서드 메타데이터 얻기
Guru99MethodMetaData.class에 있는 모든 메서드 이름 출력
Guru99MethodMetaData.class의 메서드 반환 타입 출력
Guru99MethodMetaData.class의 모든 메서드 접근 제어자 출력
Guru99MethodMetaData.class의 메서드 매개변수 타입 출력
Guru99MethodMetaData.class의 메서드가 던지는 예외 출력
예제 4: 생성자 메타데이터 얻기
다음 예제는 생성자 메타데이터를 얻는 방법을 보여줍니다:
여기에 다른 생성자들을 가진 Guru99Constructor.class라는 클래스를 만듭니다:
package guru;
import java.rmi.RemoteException;
import java.sql.SQLException;
public class Guru99Constructor {
public Guru99Constructor(int no) throws ClassCastException, ArithmeticException {
}
public Guru99Constructor(int no, String name) throws RemoteException, SQLException {
}
public Guru99Constructor(int no, String name, String address) throws InterruptedException {
}
}
여기서 Guru99Constructor.class에 있는 생성자들의 메타데이터를 얻는 클래스를 작성합니다:
package guru;
import java.lang.reflect.Constructor;
public class Guru99ConstructorMetaDataTest {
public static void main (String[] args) {
// Guru99Constructor.class의 Class 객체 생성
Class guru99Class = Guru99Constructor.class;
// Constructor 배열로 모든 생성자 정보 얻기
Constructor[] guru99ConstructorList = guru99Class.getConstructors();
for (Constructor constructor : guru99ConstructorList) {
// 각 생성자 이름 출력
System.out.println("Constructor name : " + constructor.getName());
// 각 생성자 접근 제어자 얻고 출력
int guru99Modifiers = constructor.getModifiers();
System.out.println("Constructor modifier : " + Modifier.toString(guru99Modifiers));
// 매개변수 타입 얻고 출력
Class[] guru99ParamList = constructor.getParameterTypes();
System.out.print("Constructor parameter types : ");
for (Class class1 : guru99ParamList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
// 생성자가 던지는 예외 얻고 출력
Class[] guru99ExceptionList = constructor.getExceptionTypes();
System.out.println("Exception thrown by constructors : ");
for (Class class1 : guru99ExceptionList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
System.out.println("*******************************************");
}
}
}
Guru99Constructor.class의 클래스 객체 생성
Constructor 배열로 모든 생성자 메타데이터 얻기
Guru99Constructor.class에 있는 모든 생성자 이름 출력
Guru99Constructor.class의 모든 생성자 접근 제어자 출력
Guru99Constructor.class의 생성자 매개변수 타입 출력
Guru99Constructor.class의 생성자가 던지는 예외 출력
요약:
Java 리플렉션 프로그래밍은 클래스와 클래스 멤버(변수, 메서드, 생성자)에 대한 정보 검색과 수정을 돕습니다.