코딩마을방범대

Java의 Reflection 기능을 사용하는 방법 본문

💡 백엔드/Java

Java의 Reflection 기능을 사용하는 방법

신짱구 5세 2023. 7. 26. 15:25
728x90

 

 

Reflection

  • 클래스의 구조를 분석하여 동적 로딩을 가능하게 하는 기능
  • 힙 영역에 로드된 Class 타입의 객체를 통해 원하는 클래스의 인스턴스를 생성할 수 있도록 지원하고,
    인스턴스의 필드와 메소드를 접근 제어자와 상관 없이 사용할 수 있도록 지원하는 API

 


 

 

장점

  • 런타임 시점에서 클래스의 인스턴스를 생성하고, 접근 제어자와 관계 없이 필드와 메소드에 접근하여 필요한 작업을 수행할 수 있는 유연성을 가지고 있다.

단점

  • 캡슐화를 저해한다.
  • 런타임 시점에서 인스턴스를 생성하므로 컴파일 시점에서 해당 타입을 체크할 수 없고,
    구체적인 동작 흐름을 파악하기 어렵다.
  • 단순히 필드 및 메소드를 접근할 때보다 리플렉션을 사용하여 접근할 때 성능이 느리다.
    (모든 상황에서 성능이 느리지는 않음.)

 

 

 


 

 

 

 

 

 

사용하기

 

Reflection 기능을 활용하여 가져올 수 있는 항목은 크게 네 가지가 있다.

  1. new 를 사용하지 않고 인스턴스를 생성할 수 있다.
  2. 인스턴스의 메소드를 가져올 수 있다.
  3. 인스턴스의 변수를 가져올 수 있다.
  4. 어노테이션을 가져올 수 있다.

 

 

 


 

 

Class

Reflection의 기능을 통해서 인스턴스를 생성할 수 있다.

// User 클래스의 타입을 선언한다.
Class<?> cls = User.class;

// Node 클래스의 생성자를 취득한다.
Constructor<?> constructor = cls.getConstructor();

// 생성자를 통해 newInstance 함수를 호출하여 Node 인스턴스를 생성한다.
User user = (User) constructor.newInstance();

 

 

💡 클래스 타입을 가져오는 세 가지 방법!

  1.    클래스명.class
  2.    Class.forName("경로.클래스명");
  3.    객체.getClass()

 

Class.forName() 을 통해 클래스 타입을 가져올 경우 장점!

컴파일할 때, 해당 클래스를 만들지 않아도 생성이 가능합니다.
즉, 실행할 때만 해당 클래스가 있으면 되어 동적 바인딩이 가능하다.

 

 

 


 

 

Method

Class의 Method를 가져와 실행시킬 수 있다.

// User라는 클래스의 subscribe 메소드를 가져온다.
Method method = Class.forName("User").getMethod("subscribe");

// 저장한 subscribe 메소드의 인수에 User 클래스를 넣어 실행한다.
method.invoke(Class.forName("User"));

 


 

 

💡 실행할 메소드에 파라미터가 존재하는 경우?

만약 파라미터가 있는 메소드를 실행해야할 경우에는 getMethod 시 인자의 타입을 순서대로 명시해주면 된다.

User 클래스의 print 라는 메소드의 파라미터가 (String, int) 일 경우 아래와 같이 실행하면 된다.

// 클래스에서 String, int 파라미터를 가진 print함수를 취득한다.
method = cls.getMethod("print", String.class, Integer.TYPE);

// 취득한 함수에 생성한 인스턴스와 파라미터 값을 넣고 실행시킨다.
method.invoke(user, "test2", 100);
private이나 protected 가 붙은 메소드를 활용해야할 경우?
method.setAccessible(true);

 


 

getMethods와 getDeclaredMethods의 차이점

※ @Data 어노테이션 같은 경우 Get, Set 메소드가 각각 출력됨!

메소드 설명
getMethods() 오브젝트부터 해당 클래스까지의 메소드 전부를 가져옴
( equals, toString, hashCode 등이 포함되어 있음 )
getDeclaredMethods() 해당 클래스의 메소드들을 가져옴

 

 


 

 

Variable

Class의 변수들을 가져와 사용할 수 있다.

// Reflection으로 data 변수를 취득한다.
Field field = User.class.getDeclaredField("name");

// setAccessible는 private, protected도 접근 가능하게 한다.
field.setAccessible(true);

// 인스턴스와 인수값을 주어 세팅할 수 있다.
field.set(user, 100);

 


 

getFields와 getDeclaredFields의 차이점

※ 실질적으로 변수를 public으로 선언하는 경우는 없기 때문에 Declared를 많이 사용함

메소드 설명
getFields() public 필드만 가져옴
getDeclaredFields() public과 private 필드 전부 가져옴

 

 


 

 

Annotation

클래스나 메소드 등에 부여된 어노테이션을 가져온다.

// User에서 AccessRole 이라는 클래스명을 가진 어노테이션을 가져옴
Annotation ann = User.class.getAnnotation(AccessRole.class);

// 어노테이션에 인수값으로 들어간 값을 가져옴
ann.role();

 

 

 

 

 


참고사이트

Reflection 기능을 사용하는 방법 - Class편

[Java] Reflection 개념 및 사용 방법

 

 

728x90