TestClassValidator.java
package validation;
import entities.Item;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class TestClassValidator {
public static void main(String[] args) {
validateGetters(Item.class);
}
public static void validateGetters(Class<?> targetClass) {
Field[] fields = targetClass.getDeclaredFields();
Map<String, Method> methodMapping = mapMethodsByName(targetClass);
for (Field field : fields) {
String expectedGetterName = "get" + capitalizeFirst(field.getName());
if (!methodMapping.containsKey(expectedGetterName)) {
throw new IllegalStateException(
String.format("Field '%s' does not have a corresponding getter method", field.getName()));
}
Method getterMethod = methodMapping.get(expectedGetterName);
if (!getterMethod.getReturnType().equals(field.getType())) {
throw new IllegalStateException(
String.format("Getter '%s()' has return type '%s' but expected '%s'",
getterMethod.getName(),
getterMethod.getReturnType().getTypeName(),
field.getType().getTypeName()));
}
if (getterMethod.getParameterCount() > 0) {
throw new IllegalStateException(
String.format("Getter '%s' should not accept any parameters but has %d arguments",
expectedGetterName, getterMethod.getParameterCount()));
}
}
}
private static String capitalizeFirst(String input) {
return input.substring(0, 1).toUpperCase() + input.substring(1);
}
private static Map<String, Method> mapMethodsByName(Class<?> targetClass) {
Method[] methods = targetClass.getMethods();
Map<String, Method> nameToMethodMap = new HashMap<>();
for (Method method : methods) {
nameToMethodMap.put(method.getName(), method);
}
return nameToMethodMap;
}
}
entities/Item.java
package entities;
import java.util.Date;
public class Item {
private double cost;
private String title;
private long stock;
private Date expiryDate;
// Getters
public double getCost() {
return cost;
}
public String getTitle() {
return title;
}
public long getStock() {
return stock;
}
public Date getExpiryDate() {
return expiryDate;
}
}
1. Class.getDeclaredFields()
- 설명: 클래스에 선언된 모든 필드(직렬화된 private 필드 포함)를 반환합니다.
- 사용 예:
Field[] fields = targetClass.getDeclaredFields();
- Item 클래스의 필드를 반복적으로 탐색해 Getter 메서드 검증을 수행합니다.
2. Class.getMethods()
- 설명: 클래스 및 상위 클래스에서 상속받은 모든 public 메서드를 반환합니다.
- 사용 예:
Method[] methods = targetClass.getMethods();
- 메서드 이름과 매핑하여 Map<String, Method>로 관리합니다.
3. Field.getName()
- 설명: 필드 이름을 반환합니다.
- 사용 예:
String expectedGetterName = "get" + capitalizeFirst(field.getName());
- 필드 이름을 기반으로 예상 Getter 메서드 이름을 생성합니다. 예: cost → getCost.
4. Method.getName()
- 설명: 메서드 이름을 반환합니다.
- 사용 예:
nameToMethodMap.put(method.getName(), method);
- 메서드 이름과 Method 객체를 매핑해 빠르게 검색할 수 있도록 처리합니다.
5. Method.getReturnType()
- 설명: 메서드의 반환 타입을 반환합니다.
- 사용 예:
if (!getterMethod.getReturnType().equals(field.getType())) { throw new IllegalStateException(...); }
- 필드 타입과 Getter 메서드의 반환 타입이 일치하는지 확인합니다.
6. Method.getParameterCount()
- 설명: 메서드의 파라미터 개수를 반환합니다.
- 사용 예:
if (getterMethod.getParameterCount() > 0) { throw new IllegalStateException(...); }
- Getter 메서드가 파라미터를 가지지 않아야 함을 검증합니다.
검증 과정
1. 클래스 필드 추출
Field[] fields = targetClass.getDeclaredFields();
Item 클래스의 필드인 cost, title, stock, expiryDate를 가져옵니다.
2. 메서드 매핑
Map<String, Method> methodMapping = mapMethodsByName(targetClass);
Item 클래스의 모든 public 메서드를 Map에 저장합니다.
3. Getter 검증
각 필드에 대해:
- 예상 Getter 이름 생성 (get<FieldName>).
- Getter 메서드 존재 여부 확인.
- 반환 타입과 필드 타입 일치 여부 확인.
- 파라미터 개수가 0인지 확인.
'(2024-10) 스파르타 내일배움캠프 - 백엔드 > Java Reflect' 카테고리의 다른 글
ConfigLoader 예제 (0) | 2024.11.27 |
---|---|
필드 제어 예제2) Json Serializer with Array (0) | 2024.11.27 |
Field 제어 (0) | 2024.11.27 |
Java Reflect의 Array 제어 (0) | 2024.11.27 |
Constructor 예제, 싱글턴에서(2) (0) | 2024.11.26 |