Class class = Class.forName("클래스 이름");
<정적 바인딩 vs 동적 바인딩>
바인딩이란 프로그램에 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는 행위를 의미한다. 즉, 프로그램에서 사용되는 변수나 메서드 등 모든 것들이 결정되도록 연결해주는 것을 뜻한다.
바인딩을 결정 짓는 시점에 따라 정적 바인딩, 동적 바인딩으로 나뉘게 된다.
이렇게 동적 바인딩은 실행 시간에 Binding 되다보니 정적 바인딩보다는 성능상 오버헤드가 있지만, 동적 바인딩을 통해 상속과 다형성 등 다양한 기능을 사용할 수 있는 장점이 있다.
앞서 설명했던 것을 토대로 생각해보면, Reflection은 Runtime에 Class Type을 모르는채로 객체를 생성하고 이용하기 때문에 동적 바인딩을 제공한다.
동적으로 Class를 사용 해야할 경우
- 코드 작성 시점에서는 어떠한 Class를 사용해야할지 모르지만 Runtime에 Class를 가져와서 실행해야하는 경우 (Spring Annotation)
Test Code 작성
- private 변수를 변경하고 싶거나 private method를 테스트할 경우
자동 Mapping 기능 구현
- IDE 사용 시 Da 입력만해도 이와 관련된 Class 혹은 Method 목록들을 IDE가 먼저 확인하고 사용자에게 제공한다.
Jackson, GSON 등의 JSON Serialization Library
- Reflection을 사용하여 객체 필드의 변수명/어노테이션명을 Json key와 mapping 해주고 있다.
정적 분석 tool
지금 말한 Reflection의 활용 주제 중, 가장 기대 효과가 높은 부분은 바로 동적으로 Class를 사용해야 하는 경우이다.
Reflection은 아래와 같은 정보를 가져올 수 있으며
public static void main(String[] args) throws Exception {
// 1. class를 알고 있을 경우
Class car = Car.class;
// 2. class 이름만 알고 있을 경우
Class car = Class.forName("com.reflection.test.Car");
// class.getName() -> com.reflection.test.Car
// 3. Default 생성자를 이용한 객체 생성
Car realCar = car.newInstance();
// 4. class에 구현된 interface 확인
Class[] interfaces = car.getInterfaces();
}
public static void main(String[] args) throws Exception {
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();
}
public static void main(String[] args) throws Exception {
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, /*인자*/);
}
public static void main(String[] args) throws Exception {
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
}
public static void main(String[] args) throws Exception {
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, "아반떼");
}
확장성
대량의 if/else문을 사용하는 것보다 Reflection을 이용하여 재사용 가능한 컴포넌트로 만들 수 있다.
Class 브라우저 및 시각적 개발 환경을 제공
Reflection을 통해 Method, Property, Constructor를 미리 파악함으로써 사용할 정보를 열거하여 시각적 개발 환경을 구축할 수 있다.
디버거 및 테스트 도구
디버거는 개인 Property, Method, Constructor를 검사할 수 있어야 한다. 테스트 장치는 Reflection을 사용하여 클래스에 정의된 발견 가능한 세트 API를 체계적으로 호출하여 테스트에서 높은 수준의 코드 커버리지를 보장할 수 있다.
라이브러리 파악
Java에서 지원하는 라이브러리가 아닌 특정 기업의 라이브러리를 사용하는 경우 해당 라이브러리에 존재하는 클래스 및 메서드를 분석할 수 있다.
컴파일 시점에 가는한 타입 확인이 불가능하여 캄파일 시에 타입 확인이나 예외 검사를 할 수 없다.
클래스,메서드,필드를 접근하여 직접 이용하기 때문에 객체 지향 프로그래밍의 특징인 추상화를 위반한다.
컴파일 에러가 아닌 런타임시에 에러가 발생하기 때문에 코드 운용에 위험이 있다.
📑 출처: https://velog.io/@alsgus92/Java-Reflection%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%96%B8%EC%A0%9C%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%B4-%EC%A2%8B%EC%9D%84%EA%B9%8C