조금 전에
원래대로라면
그래서 다 때려박으면서 예제삼아 코드값 <-> 텍스트 상호전환 코드까지 같이 만들었는데…
누가 (울 회사 직원이라고 말 안할거임) 그걸 그대로 복붙해서
해서 코드값 <-> 텍스트 상호전환 하는 부분을 별도의 유틸리티 클래스로 분리했다.
문제는 여기서 발생하는데…
먼저
그리고 맨 처음 유틸리티 클래스를 람다식을 활용하여 만들었다.
그리고 테스트를 돌렸을 때, 처음 보는 당황스러운 에러가…
…모라고요?
곰곰히 머리를 싸매고 생각하다가 분석을 해보니
그래서 람다 말고 메소드 직접 호출로 변경.
이러니까 잘 된다.
이게
enum
들에 널려있는 중복 코드들을 제거하는 와중에 일어난 이야기.원래대로라면
enum
에는 코드값만 넣고 텍스트는 따로 properties
에 빼놓는데, 이번 고객은 아아주 특이하게도 그렇게 하면 유지보수하기 귀찮다고 소스에 다 때려박아달랜다.그래서 다 때려박으면서 예제삼아 코드값 <-> 텍스트 상호전환 코드까지 같이 만들었는데…
누가 (울 회사 직원이라고 말 안할거임) 그걸 그대로 복붙해서
enum
수십 개를 만들었고, CPD는 복붙 고마해라 라고 지랄대고…해서 코드값 <-> 텍스트 상호전환 하는 부분을 별도의 유틸리티 클래스로 분리했다.
문제는 여기서 발생하는데…
먼저
WithCodeLabel
이라는 인터페이스를 만들고 메소드를 정의한 다음, 해당 enum
들에 implements
를 걸었다.그리고 맨 처음 유틸리티 클래스를 람다식을 활용하여 만들었다.
public class EnumCodeLabelCache<E extends Enum<E> & WithCodeLabel> {
private final Map<String, E> codeToLabelMap;
private final Map<String, E> labelToCodeMap;
private EnumCodeLabelCache(Class<E> cls) {
final EnumSet<E> set = EnumSet.allOf(cls);
codeToLabelMap = set.stream().collect(Collectors.toMap(WithCodeLabel::getCode, Function.identity());
labelToCodeMap = set.stream().collect(Collectors.toMap(WithCodeLabel::getLabel, Function.identity());
}
...
}
그리고 테스트를 돌렸을 때, 처음 보는 당황스러운 에러가…
java.lang.BootstrapMethodError: call site initialization exception
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
…모라고요?
곰곰히 머리를 싸매고 생각하다가 분석을 해보니
enum
의 각 값의 RTTI에 WithCodeLabel
인터페이스에 대한 정보가 누락되어 있다는 결과밖에 나오지를 않는다.그래서 람다 말고 메소드 직접 호출로 변경.
public class EnumCodeLabelCache<E extends Enum<E> & WithCodeLabel> {
private final Map<String, E> codeToLabelMap = new HashMap<>();
private final Map<String, E> labelToCodeMap = new HashMap<>();
private EnumCodeLabelCache(Class<E> cls) {
final EnumSet<E> set = EnumSet.allOf(cls);
set.forEach(e -> {
codeToLabelMap.putIfAbsent(e.getCode(), e);
labelToCodeMap.putIfAbsent(e.getLabel(), e);
});
}
...
}
이러니까 잘 된다.
이게
enum
만 특히 이런건지, 제네릭 특징인지는 더 살펴봐야 알겠지만, 내가 알 게 뭐야.
0 개의 댓글:
댓글 쓰기