티스토리 뷰

java_basic

Build 패턴 NullPointException, ArrayList

✨✨✨✨✨✨✨ 2023. 6. 10. 12:42
반응형
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {
    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private long id;
    private int age;

    private String username;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    public void changeTeam(Team team) {
        this.team = team;
        System.out.println("team :" + team);

        Member member = this;
        System.out.println("member :" + member);

        List<Member> members = team.getMembers();
        System.out.println("members :" + members);

        members.add(member);

    }
}​
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
@Getter
public class Team {
    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private long id;
    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

    public Team(String name, List<Member> members) {
        this.name = name;
        this.members = members;
    }

    public Team(String name) {
        this.name = name;
    }
}
    @RequestMapping("/test")
    @Transactional
    public void test(){
        Team team = new Team("team2", new ArrayList<>());
        Team team2 = new Team("team3");
        Team team3 = Team.builder().name("develop").build();

        em.persist(team);

        System.out.println(team.getMembers());
        System.out.println(team2.getMembers()); 
        System.out.println(team3.getMembers()); // NullPontException
}

마지막 team3의 경우에만 team3.getMembers를 하니 NullPointException이 발생하였다.

 

원인을 확인해보니, Builder 패턴으로 작성한 경우에는 내부에 선언된 List members = new ArrayList();로 데이터를 초기화 안해준다고 한다.

Build 패턴으로 생성된 `team` 객체의 `members` 필드가 `null`인 이유는 `members` 필드에 대한 초기화가 `@Builder` 어노테이션에 의해 자동으로 처리되지 않았기 때문입니다.

 

`@Builder` 어노테이션은 빌더 패턴을 사용하여 객체를 생성할 때 필드 초기화를 자동으로 처리해주는 기능을 제공합니다. 그러나 `members` 필드는 `ArrayList`로 선언되었지만, `@Builder` 어노테이션에서 해당 필드를 초기화하는 설정이 포함되어 있지 않아서 `null`로 초기화되었습니다.

 

반면에 `team2`와 `team3` 객체는 직접 생성자를 통해 초기화되었기 때문에 `members` 필드에는 명시적으로 빈 리스트(`new ArrayList<>()`)가 할당되어 있습니다. `ArrayList` 생성자 호출에 의해 새로운 빈 리스트가 생성되고, 이를 `members` 필드에 할당함으로써 `null`이 아닌 빈 리스트가 됩니다.

 

따라서, `team` 객체의 `members` 필드를 초기화하려면 `@Builder` 어노테이션 설정에서 `members` 필드에 대한 초기화를 추가해주어야 합니다. 예를 들면 다음과 같이 할 수 있습니다:

@Builder
public class Team {
    // ...

    @Builder.Default
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

    // ...
}

`@Builder.Default` 어노테이션을 사용하여 `members` 필드를 기본값으로 초기화할 수 있습니다. 이렇게 설정하면 `team.getMembers()`는 빈 리스트로 초기화됩니다.

 

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함