나는 어차피 잘 될 사람이다.
어차피 잘 될 것이고, 지금도 잘 되고있고, 과거도 잘 되어왔기에,,,
이전에 썻던 DI에 관한 글에서 final
키워드에 대한 생각을 정리하긴 했는데, 그 때는 인스턴스 필드에 final
을 주는 이유에 대해서, 값이 변경 되는 것을 막기 위해서 라고 생각했다.
이것도 물론 맞는 말인데, 코드에 대해서 의문점이 들었다.
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
해당 코드에 오류가 없다. 그런데,
생성자 중 윗 줄을 하나 지웠다.
그런데 한 곳에서 뻘건 줄이 뜬다.
에러 메세지
Variable 'memberRepository' might not have been initialized
이렇게 나오는데,
이렇단다.
그리고 뻘건 줄 쪽에 final
키워드 지워봤다.
애매한데 그래도 에러는 없다.
final
이 없고, 생성자로 아무것도 넣어주지 않으면, null
을 허용할 수 있다는 의미인데, final을 다시 넣으면, 에러가 나왔다...
이건 단순히 스프링 보단 final
의 키워드에 대한 개념이 부족한 듯... 찾아봤다.
음.. 스프링보단 final
의 개념에 대해 한번 더 보게 되었다.
일단 final
을 선언하면, 변경이 불가능한(불변) 상태가 되며, 그렇기 때문에 선언시 초기화를 동시에 해주어야 한다.
그런데, 인스턴스 변수의 경우에는 생성자에서 초기화 되도록 할 수 있다고 한다.
즉 생성자의 매개변수로 final이 붙은 필드를 초기화할 수 있다.
(자바의 정석 3판 346페이지참고)
그래서
private final MemberRepository memberRepository = new MemberRepository();
이런식으로 선언과 동시에 초기화 해야하지만, DI(의존성 주입)을 통해서 스프링 컨테이너에 올라간 Bean
을 인스턴스 생성시 생성자 주입을 통해서 final
이 붙은 인스턴스 필드에 Bean객체를 주입해줄 수 있다.
그리고 번외로 생성자 주입을 해야,
변경 불가능한 불변성을 지키며, 혹여나 이후에 생길 변경으로 인한 문제를 예방할 수 있다.
-끝-