-
Notifications
You must be signed in to change notification settings - Fork 0
김현욱, 최현식 리플렉션
HyeonSik Choi edited this page Jul 8, 2024
·
6 revisions
- 김현욱
- 리플렉션을 직접 사용하는 일은 거의 없었습니다. 프레임워크에서 만들어진 annotation을 사용했으며, 만들어도 간단한 기능의 annotation을 만들어 사용했기 때문에 reflection에 대한 개념을 잊을 수 있었습니다.
- 이번 미션을 통해 reflection을 리마인드 할 수 있어서 재밌었습니다.
- 최현식
- 리플렉션을 사용해본지도 오래되어서 새로웠습니다. 잘모르고 있던 것이 아닌가 라는 생각이 들었습니다.
- 리플렉션을 이용하면 클래스의 정보, 생성자, 필드, 메서드 정보를 모두 확인할 수 있습니다.
- 리플렉션을 이용하면 컴파일된 모든 클래스에 접근할 수 있고, 심지어 private 접근제어자도 무시할 수 있어, 잘못 사용하면 큰 책임이 따르겠다고 느꼈습니다.
- 지금껏 코딩을 하면서 리플렉션을 활용하는 일이 거의 없었습니다. 따라서 '이걸 사용할 일이 많을까?' 하는 생각도 들었습니다.
- WAS 미션에서 리플렉션과 어노테이션을 이용하면 더 깔끔하게 코드를 관리할 수 있을 것 같습니다 :)
- 리플렉션 API는 컴파일한 클래스 정보를 활용해 동적으로 프로그래밍이 가능하도록 지원하는 API로,
- 자바에서는 JVM이 클래스 로더를 통해 정보를 불러와 실행시키는 구조이기 때문에, 런타임에 클래스, 함수 등의 정보를 가져올 수 있습니다.
- Junit에서 @Test 애노테이션이 설정되어 있는 메소드를 단위 테스트로 실행하고 싶다.
- 현재 실행하는 클래스의 클래스, 필드, 메소드 정보를 알고 싶어요.
- 인자로 전달하는 클래스의 인스턴스를 생성한 후 메소드를 실행하고 싶어요.
- Eclipse/Intellij IDEA가 동적으로 setter와 getter 메소드를 만드는 방법이 뭘까요?
- 데이터베이스에서 조회한 데이터의 칼럼 이름과 자바 클래스의 필드 이름이 같은 경우 자동으로 매핑하고 싶어요.
고수준 언어에는 대부분 존재하는 편!
- C++: 애매함! 리플렉션은 없지만, 템플릿이나 메타정보 정도는 접근할 수 있음
- C#: 존재함! 닷넷에 가상머신같은게 존재함
- Python: 존재함! 인터프린터 언어에는 유사하게 모두 존재
어노테이션은 주석과 유사하지만 Retention 명시에 따라 그 생명주기가 달라집니다.
- SOURCE: 컴파일 시점까지 유지. 소스 코드에서만 존재
- 예: @Override, @SuppressWarnings
- CLASS: 컴파일 후 클래스 파일에 유지. 런타임에는 사라짐
- 예: @Configuration
- RUNTIME: 컴파일 후 클래스 파일에 유지. 런타임에도 유지
- 예: @Autowired, @Transactional, @RequestMapping
//HelloWorld.class
package next;
public class HelloWorld {
private int age;
private String name;
public HelloWorld(String name,int age){
this.age = age;
this.name = name;
}
}
Compile 한 결과
// class version 55.0 (55)
// access flags 0x21
public class next/HelloWorld {
// compiled from: HelloWorld.java
// access flags 0x2
private I age
// access flags 0x2
private Ljava/lang/String; name
// access flags 0x1
public <init>(Ljava/lang/String;I)V
L0
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
L1
LINENUMBER 7 L1
ALOAD 0
ILOAD 2
PUTFIELD next/HelloWorld.age : I
L2
LINENUMBER 8 L2
ALOAD 0
ALOAD 1
PUTFIELD next/HelloWorld.name : Ljava/lang/String;
L3
LINENUMBER 9 L3
RETURN
L4
LOCALVARIABLE this Lnext/HelloWorld; L0 L4 0
LOCALVARIABLE name Ljava/lang/String; L0 L4 1
LOCALVARIABLE age I L0 L4 2
MAXSTACK = 2
MAXLOCALS = 3
}
// class version 55.0 (55)
// access flags 0x21
클래스의 헤더 정보를 나타냅니다.
public class next.HelloWorld {
next.HelloWorld 클래스의 선언부입니다.
// access flags 0x2
private I age
// access flags 0x2
private Ljava/lang/String; name
age
필드와 name
필드를 정의하는 부분입니다.
// access flags 0x1
public <init>(Ljava/lang/String;I)V
생성자를 정의하는 부분입니다.
-
<init>
: 생성자 메서드의 이름입니다. JVM에서 생성자를 나타내는 표기입니다. -
Ljava/lang/String;I
: 생성자의 파라미터 타입을 나타내는 부분입니다. String타입과 int를 인자로 받는 생성자를 정의하고 있습니다.
L0
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
-
L0
: 라벨링 기호로, 이후 명령어들이 참조할 수 있는 코드 블록의 시작점을 나타냅니다. -
LINENUMBER 6 L0
: 소스 코드의 6번째 줄에 해당하는 명령어 위치를 나타냅니다. -
ALOAD 0
: 로컬 변수 스택에서 인덱스 0에 해당하는 값을 로드합니다. 이는this
를 로드하는 작업입니다. -
INVOKESPECIAL java/lang/Object.<init> ()V
:Object
클래스의 생성자를 호출합니다. 모든 클래스의 최상위 클래스인Object
의 기본 생성자를 호출하여 객체 초기화를 수행합니다.
L1
LINENUMBER 7 L1
ALOAD 0
ILOAD 2
PUTFIELD next/HelloWorld.age : I
L2
LINENUMBER 8 L2
ALOAD 0
ALOAD 1
PUTFIELD next/HelloWorld.name : Ljava/lang/String;
-
L1
: 새로운 코드 블록의 시작점을 나타냅니다. -
LINENUMBER 7 L1
: 소스 코드의 7번째 줄에 해당하는 명령어 위치를 나타냅니다. -
ALOAD 0
: 로컬 변수 스택에서 인덱스 0에 해당하는 값을 로드합니다. 여기서는 생성된 객체(this
)를 가리킵니다. -
ILOAD 2
: 로컬 변수 스택에서 인덱스 2에 해당하는 값을 로드합니다. 이는int age
생성자 파라미터를 의미합니다. -
PUTFIELD next/HelloWorld.age : I
:next.HelloWorld
객체의age
필드에 값을 할당합니다. -
ALOAD 1
: 로컬 변수 스택에서 인덱스 1에 해당하는 값을 로드합니다. 이는String name
생성자 파라미터를 의미합니다. -
PUTFIELD next/HelloWorld.name : Ljava/lang/String;
:next.HelloWorld
객체의name
필드에String
값을 할당합니다.
L3
LINENUMBER 9 L3
RETURN
-
L3
: 새로운 코드 블록의 시작점을 나타냅니다. -
LINENUMBER 9 L3
: 소스 코드의 9번째 줄에 해당하는 명령어 위치를 나타냅니다. -
RETURN
: 현재 메서드를 종료하고 호출자에게 반환합니다.
L4
LOCALVARIABLE this Lnext/HelloWorld; L0 L4 0
LOCALVARIABLE name Ljava/lang/String; L0 L4 1
LOCALVARIABLE age I L0 L4 2
MAXSTACK = 2
MAXLOCALS = 3
-
LOCALVARIABLE
: 지역 변수의 선언을 나타냅니다.this
,name
,age
가 각각 0, 1, 2번 인덱스로 선언되어 있음을 보여줍니다. -
MAXSTACK = 2
: 메서드에서 사용할 수 있는 최대 스택 깊이를 나타냅니다. 여기서는 2개의 항목을 사용할 수 있음을 의미합니다. -
MAXLOCALS = 3
: 메서드에서 사용할 수 있는 최대 지역 변수 개수를 나타냅니다. 여기서는 3개의 지역 변수를 사용할 수 있음을 의미합니다.