private static 으로 인한 nullpointerexception

이혜은·2022년 5월 9일
0

오류

목록 보기
1/1

MemoryMemberRepository 생성시 Map에 static을 붙여주지 않으면 생기는 문제

스프링 핵심 원리 - 기본편(김영한), 섹션2-8(주문과 할인 도메인 실행과 테스트)

OrderApp에는 MemberServiceImpl과 OrderServiceImpl 인스턴스를 동시에 생성한다.

/*1*/ package hello.core;
/*1*/
/*1*/ import hello.core.member.Grade;
/*1*/ import hello.core.member.Member;
/*1*/ import hello.core.member.MemberService;
/*1*/ import hello.core.member.MemberServiceImpl;
/*2*/ import hello.core.order.Order;
/*3*/ import hello.core.order.OrderService;
/*4*/ import hello.core.order.OrderServiceImpl;
/*5*/
/*6*/ public class OrderApp { // Test 대신
/*7*/     public static void main(String[] args) {
/*8*/         MemberService memberService = new MemberServiceImpl();
/*9*/         OrderService orderService = new OrderServiceImpl();
/*10*/ 
/*11*/         Long memberId = 1L;
/*12*/         Member member = new Member(memberId, "memberA", Grade.VIP);
/*13*/         memberService.join(member);
/*14*/ 
/*15*/         Order order = orderService.createOrder(memberId, "itemA", 10000);
/*16*/         System.out.println("order = " + order);
/*17*/     }
/*18*/ }

MemberServiceImpl과 OrderServiceImpl 코드를 보면 둘 다 MemoryMemberRepository 인스턴스를 생성한다. OrderApp의 13번째 줄에서 join 하여 저장한 member의 저장소와 orderService.createOrder()해서 저장되는 member의 저장소(MemoryMemberRepository) 클래스의 내부의 실질적인 저장소인 Map 필드가 각각 다르다.

→ MemoryMemberRepository를 작성할 때 Map에 static을 붙이면 된다.

package hello.core.member;

import java.util.HashMap;
import java.util.Map;

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>(); // Member를 저장할 MemoryMemberRepository의 저장소

    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}

static을 Map 인스턴스 생성시 붙여주면, OrderServiceImpl or MemberServiceImpl에서 MemoryMemberRepository 인스턴스 생성과 관계없이 같은 Map 필드를 가지기 때문에, 같은 Map에 Member가 저장되고 그 Member 의 Grade에 의해 할인을 적용한 주문이 완성된다.
→ AppConfig(구성영역)와 같이 사용 영역과 객체를 생성하고 구성하는 영역으로 분리하면 더 이상 static을 Map에 붙여주지 않아도 된다.

@Configuration
public class AppConfig {
    @Bean // 스프링 컨테이너에 등록됨
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    	}
    }

private, static

private: 해당 클래스 내에서만 접근 가능
static: 해당 클래스의 인스턴스를 통하지 않고서도 접근 가능
📌 인스턴스변수는 하나의 클래스로부터 생성되었더라도 각 인스턴스마다 다른 값을 유지한다. 클래스변수(static 변수)는 인스턴스에 상관없이 같은 값을 갖는다.

0개의 댓글