문제 상황
- enum은 제네릭으로 만들 수 없음
- enum Operator<T extends Number> {}불가능
- private final Operate<T> op 불가능
- 하지만 op 는 값이 타입이 정해지지 않은, 알 수 없는 타입
- 때문에 와일트 카드(?)를 사용했으나, T를 ?에 넣을 수 없음 → 타입 불일치
- if (a instanceof Integer) 조건문을 사용해도 해결되지 않음
enum Operator {
ADD('+', (a, b) -> a.doubleValue() + b.doubleValue()),
...
private final Operate<?> op;
Operator(char symbol, Operate<?> op){
this.symbol = symbol;
this.op = op;
}
}
@FunctionalInterface
public interface Operate<T extends Number> {
T apply(T a, T b) throws Exception;
}
public <T extends Number> T invoke(T a, T b) {
Number result = op.apply(a, b); // ❌ 여기서 컴파일 에러 발생
...
}
에러 메시지
필요한 타입 | 제공된 타입 | |
a | capture of ? | T |
b | capture of ? | T |
실행 시
java: incompatible types: T cannot be converted to capture#1 of ?
해결 방법
- 타입을 상위 클래스 Number로 고정
- Integer, Double 등 Number의 모든 하위 타입을 처리할 수 있다.
- invoke 메서드에서는 런타임 타입에 따라 결과를 가공해 반환하면 된다.
private final Operate<Number> op;
public <T extends Number> T invoke(T a, T b) throws Exception {
Number result;
if(a instanceof Integer){
result = op.apply(a, b).intValue();
} else if(a instanceof Double){
result = op.apply(a, b).doubleValue();
} else {
throw new IllegalArgumentException("정수나 실수 타입이 아닙니다.");
}
@SuppressWarnings("unchecked")
T castedResult = (T) result;
return castedResult;
}
배운 점
- Java 제네릭에서 ?는 읽기 전용, 구체적인 타입이 필요할 때는 명확한 타입 지정이 필요하다.
- enum은 타입 파라미터를 사용할 수 없으므로, 타입 유연성이 제한된다.
- 실용적인 해결책으로 상위 타입 고정 + 런타임 처리 전략을 사용할 수 있다.
여담 .
요구사항을 맞추기 위해 제네릭을 사용했지만, (과제 키워드: 제네릭)
요구사항이 없었다면 굳이 제네릭을 사용하지 않고, Number 타입을 사용했을 것 같다. 😅
'Java > 문제 해결 (Troubleshooting)' 카테고리의 다른 글
List.of()로 만든 리스트에서 add()가 안 되는 이유 (0) | 2025.04.30 |
---|---|
반복문 안에서 InputMismatchException 예외 발생 시 무한 루프 발생 (0) | 2025.04.18 |