Search

ClassCastException - 왜 Optional 을 사용할 수 없을까?

태그
JPA

처음보는 Exception 🫣

로그인한 유저를 컨텍스트 홀더에서 꺼내서 건내려는데…
@Component @RequiredArgsConstructor public class AuthUtil { private final TokenUtil tokenUtil; public Long getLoginUserIndex() { Optional<User> user = getLoginUser(); Long userId = user.get().getId(); return userId; } public Optional<User> getLoginUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Object principal = authentication.getPrincipal(); return (Optional<User>) principal; } ...
Java
복사
으잉?
호다닥 에러문구를 보니 아래와같은 에러가 저를 반겨주었습니다.
java.lang.ClassCastException: class com.example.budget.domain.user.User cannot be cast to class java.util.Optional (com.example.budget.domain.user.User is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @2d7e1886; java.util.Optional is in module java.base of loader 'bootstrap') at com.example.budget.global.util.AuthUtil.getLoginUser(AuthUtil.java:25) ~[classes/:na]
Plain Text
복사
대략 user 를 찾을때 Optional 인게 문제인것 같은데… 왜 그런걸까요?

Optional<T> 로 Casting 될 수 없나요?

Optional<T> 은 null 이 올 수 있는 값을 감싸는 Wrapper 클래스 입니다. 이를 통해 Null Pointer Exception 을 방지할 수 있습니다. 또한 각종 메서드를 제공하기도 하죠.
그럼 casting 은 뭘까요? casting 은 특정한 객체가 다른 유형의 instance 인 것처럼 처리되어야 함을 컴파일러에게 알리는 방법 입니다. 단, 이 프로세스는 실제로 cast 되는 객체가 대상 유형 혹은 하위 클래스의 instance 인 경우에만 작동합니다.
Opitonal<T> 안에는 객체가 들어가니까 casting 될 수 있는거 아닌가? 라고 생각할 수도 있습니다. Optional<T>의 T 또는 일반 유형은 모든 유형의 객체에 대한 자리 표시자 입니다. 객체 자체가 아니라 나중에 지정하게 될 유형을 나타내는 기호라는 점에서 우리가 일반적으로 생각하는 객체가 아닙니다.
즉, 객체는 구조와 목적이 근본적으로 다르기 때문에 Optional<T>로 직접 처리할 수 없습니다. 객체는 무엇이든 될 수 있지만 Optional<T>는 특히 T 유형 객체의 컨테이너 이기 때문이죠. (비유하자면 객체 와 T 는 사과, Optional<T> 는 사과가 들어있는 박스라고 할 수 있습니다.)
그래서 아래와 같이 Optional 을 제외해주었고, 결과는 제대로 나왔습니다.
public Long getLoginUserIndex() { User user = getLoginUser(); Long userId = user.getId(); return userId; } public User getLoginUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Object principal = authentication.getPrincipal(); return (User) principal; }
Java
복사