자바(Java)와 닷넷(.NET)의 Reflection(리플렉션) 기능을 비교해보겠습니다.
리플렉션은 클래스, 메서드, 필드 등의 메타데이터를 런타임에 동적으로 조회하고 조작하는 기능을 제공합니다.
1. 주요 차이점
비교 항목 | Java (Reflection API) | .NET (System.Reflection) |
네임스페이스 | java.lang.reflect | System.Reflection |
클래스 정보 조회 | Class<?> 사용 | Type 사용 |
메서드 호출 | Method.invoke() | MethodInfo.Invoke() |
필드 값 변경 | Field.set() | FieldInfo.SetValue() |
생성자 호출 | Constructor.newInstance() | ConstructorInfo.Invoke() |
성능 | 일반 호출보다 느림 (JVM 최적화 가능) | 일반 호출보다 느림 (JIT 최적화 가능) |
보안 제한 | setAccessible(true) 필요 | BindingFlags 사용 가능 |
2. Java 리플렉션 예제
아래는 Java에서 리플렉션을 사용하여 클래스 정보를 조회하고 메서드를 호출하는 예제입니다.
🔹 Person 클래스 정의
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, my name is " + name);
}
}
🔹 리플렉션 코드
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 1. 클래스 정보 가져오기
Class<?> clazz = Class.forName("Person");
// 2. 생성자 가져오기 및 객체 생성
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
Object person = constructor.newInstance("John");
// 3. 필드 수정 (private 접근 허용)
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(person, "Alice");
// 4. 메서드 호출
Method method = clazz.getDeclaredMethod("sayHello");
method.invoke(person); // 출력: "Hello, my name is Alice"
}
}
3. .NET 리플렉션 예제 (C#)
.NET에서는 System.Reflection 네임스페이스를 사용합니다.
🔹 Person 클래스 정의
using System;
public class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public void SayHello()
{
Console.WriteLine($"Hello, my name is {name}");
}
}
🔹 리플렉션 코드
using System;
using System.Reflection;
class ReflectionExample
{
static void Main()
{
// 1. 타입 정보 가져오기
Type type = typeof(Person);
// 2. 생성자 가져오기 및 객체 생성
ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(string) });
object person = constructor.Invoke(new object[] { "John" });
// 3. 필드 수정 (private 접근 허용)
FieldInfo field = type.GetField("name", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(person, "Alice");
// 4. 메서드 호출
MethodInfo method = type.GetMethod("SayHello");
method.Invoke(person, null); // 출력: "Hello, my name is Alice"
}
}
4. Java와 .NET 리플렉션 비교 요약
기능 | Java | .NET |
클래스 정보 조회 | Class<?> clazz = Class.forName("Person"); | Type type = typeof(Person); |
생성자 호출 | Constructor<?> constructor = clazz.getDeclaredConstructor(String.class); | ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(string) }); |
필드 접근 | Field field = clazz.getDeclaredField("name"); field.setAccessible(true); | `FieldInfo field = type.GetField("name", BindingFlags.NonPublic |
메서드 호출 | Method method = clazz.getDeclaredMethod("sayHello"); method.invoke(person); | MethodInfo method = type.GetMethod("SayHello"); method.Invoke(person, null); |
5. 성능 고려사항
- 리플렉션은 정적 호출보다 성능이 느리며, 남용하면 애플리케이션 속도에 영향을 줄 수 있습니다.
- Java에서는 JVM의 최적화가 일부 가능하지만, setAccessible(true)를 사용하면 보안 문제가 발생할 수 있습니다.
- .NET에서는 JIT 최적화가 일부 가능하지만, BindingFlags를 사용하면 필드/메서드 접근 속도가 추가로 저하될 수 있습니다.
- 대안으로 동적 프록시(Java의 Proxy, .NET의 DynamicMethod) 또는 Expression Tree(C#)를 활용하면 성능 저하를 줄일 수 있습니다.
6. 결론
- 기능적으로 Java와 .NET의 리플렉션은 매우 유사하지만, 네임스페이스 및 API 스타일에 차이가 있습니다.
- Java에서는 Class, Method, Field 클래스를 사용하고, .NET에서는 Type, MethodInfo, FieldInfo 등을 사용합니다.
- 성능상 일반적인 코드보다 느리므로, 리플렉션 사용을 최소화하는 것이 좋습니다.
'프로그래밍' 카테고리의 다른 글
자바와 닷넷 비교 - final과 sealed, final과 readonly and const (0) | 2025.03.02 |
---|---|
자바와 닷넷 문자열 비교 (2) | 2025.03.02 |
자바와 닷넷 비교 - ENUM (0) | 2025.03.02 |
자바와 닷넷 날짜 함수 비교 (0) | 2025.03.02 |
자바와 닷넷의 상속 비교 (0) | 2025.03.02 |