일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- MSA
- python
- 점근적 표기법
- 백준 장학금
- 이분탐색이란
- heapq
- Kruskal
- 알고리즘
- 최소힙
- jpa n+1 문제
- HTTP
- 엔티티 그래프
- 백준장학금
- 강화학습
- spring
- 멀티프로세서
- SpringSecurity
- 운영체제
- JPA
- 완전이진트리
- 최대 힙
- JVM
- AVL트리
- 연결리스트 종류
- 프로세스
- 힙트리
- 자료구조
- 연결리스트
- 스케줄링
- posix
- Today
- Total
KKanging
[JAVA] Reflection을 알아보자 본문
리플랙션을 알기위한 사전 준비
자바 프로그램은 어떻게 실행 될까?

제일 처음 우리가 작성한 자바 소스 코드는 javac (jdk 포함되어 있음)에 의해 컴파일 된다.
그럼 이제 JVM이 이해 할 수 있는 JAVA Byte Code (.class) 로 변환된다.
그리고 이제 main 함수부터 클래스 로딩되어 Method Area 라는 메모리 영역에 올라간다.
클래스 내부에 다른 클래스를 의존하면 해당 클래스는 처음에는 심볼릭 링크의 형태로 클래스를 참조한다.
해당 심볼릭 링크 부분이 실행될 때 물리 주소로 변환된다.
다음 클래스를 호출하면 해당 클래스가 런타임(실행 중)에 로딩되는 구조이다.
우리가 작성한 코드가 변경된다고?
위에는 우리가 작성한 소스코드가 실행될 때 과정을 아주 요약하였다.
그런데 요약된 내용을 보면 작성한 자바 코드가 변경되는 순간이 3번이 있다.
- 컴파일 (정적 바인딩)
- 클래스 로딩
- 동적 바인딩
위에 3가지 순간에 우리가 작성한 코드가 변경될 수 있는 것을 볼 수 있다.
정적 바인딩과 동적 바인딩

말은 어려워 보이지만 간단하다.
정적 바인딩은 프로그램 실행이 되어도 변하지 않는 것들을 컴파일러가 컴파일 시간에 결정한다. (심볼릭 링크가 아닌 physical link )
하지만 동적 바인딩은 실행시에 정확한 링크를 알아내는 것들이다.
오버로딩과 오버라이딩을 생각하면 편하다.
여기서 정적 바인딩이 런타임 때 변하지 않는 것을 결정하는 것이지 컴파일 시간 때 코드가 변경되지 않는다와는 완전히 다른 말이다.
(해당 주제는 너무 길어지기 때문에 여기서 다루지 않는다)
reflection
리플랙션은 자바 jdk 1.1부터 제공해주는 국밥 API이다.
하도 리플랙션 리플랙션하는데 도대체 리플랙션은 무엇일까
리플랙션이란
리플랙션은 위에 동적 바인딩 시점에서 프로그래밍을 더욱 유연하게 할 수 있게끔 JAVA 에서 제공해주는 API 이다.
프로그램 시점에 구체적인 클래스 타입을 알지 못하더라도 해당 클래스의 메서드, 타입, 변수들에 접근 할 수 있도록 해주는 자바 API 이다.
대충 요약을 하자면 위에 자바가 실행되는 설명에서 클래스가 로딩되면 메모리에 점유한다 했다.
해당 클래스의 정보들이 로딩되면 메모리 위에 점유하는데 이 때 점유된 클래스의 정보 가지고 동적으로 실행이 가능하도록 해준다.
리플랙션의 기능
리플랙션은 class의 정보를 제공한다는 점에 주목해야한다.
class 에는 어떤 정보들이 있을까
필드(state)
메서드(Behavial)
클래스 이름
Constructor (생성자)
어노테이션
static 메서드
상속한 부모 인터페이스 및 클래스
class 로드하기
Class car = Car.class;
Class car = Class.forName("com.reflection.test.Car");
constructor
Class car = Class.forName("com.reflection.test.Car");
// 1. 인자가 없는 생성자 가져오기
Constructor constructor = car.getDeclaredConstructor();
// 2. String 인자를 가진 생성자 가져오기
Constructor constructor = car.getDeclaredConstructor(String.class);
// 3. 모든 생성자 가져오기
Constructor constructors[] = car.getDeclaredConstructors();
// 4. public 생성자만 가져오기
Constructor constructors[] = car.getConstructors();
// public com.reflection.test.Car()
// public com.reflection.test.Car(java.lang.String)
// 5. 생성자를 이용한 객체 생성
Car realCar = constructor.newInstance();
Method
Class car = Class.forName("com.reflection.test.Car");
// 1. 인자가 없는 method 가져오기
Method method = car.getDeclaredMethod("move");
// 2. String 인자를 가진 method 가져오기
Method method = car.getDeclaredMethod("move", String.class);
// 3. 모든 method 가져오기
Method methods[] = car.getDeclaredMethods();
// 4. 상속받은 method와 public method 가져오기
Method methods[] = car.getMethods();
// public void com.reflection.test.Car.move()
// public void com.reflection.test.Car.move(java.lang.String)
// 5. method 호출
Class realCar = car.newInstance();
method.invoke(realCar, /*인자*/);
// 6. 접근 제한자를 무시한 method 호출.
method.setAccessible(true);
method.invoke(realCar, /*인자*/);
Field
Class car = Class.forName("com.reflection.test.Car");
// 1. car 객체에서 name 에 해당하는 field 가져오기
Field field = car.getDeclaredField("name");
// 2. car + car super 객체를 포함하여 name에 해당하는 field 가져오기
Field field = car.getField("name");
// 3. car 객체에 선언된 모든 field 가져오기
Field[] fields = car.getDeclaredFields();
// private java.lang.String com.reflection.test.Car.name
// public java.lang.Integer com.reflection.test.Car.type
// 4. car + car super 객체의 모든 public field 가져오기
Field[] fields = car.getFields();
// public java.lang.Integer com.reflection.test.Car.age
Field 값 변경
Class class = Class.forName("com.reflection.test.Car");
Constructor constructor = class.getConstructor()
Car car = constructor.newInstance()
Field field = car.getField("name");
// 1. public field 일 경우
field.set(car, "아반떼");
// 2. private field 일 경우
field.setAccessible(true);
field.set(car, "아반떼");
https://velog.io/@alsgus92/Java-Reflection은-무엇이고-언제어떻게-사용하는-것이-좋을까
이외에도 class에 붙어 있거나 method에 붙은 어노테이션을 가지고 올 수 도 있고
접근 제어자가 private 이든 가지고 오고 심지어 제어자 레밸 변경도 가능하다. ㄷㄷ
상속하는 상속 클래스 및 인터페이스도 로딩이 가능하다.
리플랙션의 장단점
장점
리플랙션은 유연한 개발이 가능하다는 점에서 개발자 관점에서 다양한 구현이 가능하다.
잘 사용하면 유지보수 관점에서 아주 실용적으로 사용이 가능하다.
단점
위에서 예제나 기능을 봤듯이 접근 제어자나 객체의 프로퍼티도 변경이 가능하다.
그리고 무엇보다 런타임 시에 오류가 발생하기 때문에 디버깅에도 어려움이 많다.
그리고 리플랙션을 남발하면 성능에도 문제가 생길 수 있다.
리플랙션 단점이 더 많아 보이는데 중요한가?
리플랙션은 물론 단점이 치명적이다.
실제로 리플랙션을 쌩으로 사용하는 개발자는 몇 없을 것이다.
대신 오늘 날에 동적 프록시, Spring AOP 등이 리플랙션의 기능을 이용한 기술이기 때문에 알아 놓을 필요가 있다.
'JAVA > 언어' 카테고리의 다른 글
JAVA enum을 왜 사용하는 걸까? (1) | 2024.09.30 |
---|---|
[JAVA] ThreadLocal (0) | 2024.05.18 |