자바 객체 초기화에 관하여

멀리보다·2021년 9월 4일
0

java

목록 보기
1/1

c# 고인물 개발자가 java하려니 불편한게 한 두개가 아니다.

그중 하나가 자바에는 property가 없다는 것.

Property는 getter, setter 메서드가 포함된 멤버 변수라 생각하면 별거 아니지만,

자바는 Property가 없으니 Object Initializer가 없다. 이게 없으니 필요한 몇몇 멤버 값을 세팅하는데 불편함이 있다.

테스트 데이터를 만들어야 하는데 object initializer이 없으니 너무 불편하고 코드가 장황해져서 방법을 찾던 중 {{ }} (이중 중괄호)를 이용하여 java8 이후 setter를 호출 하는 방법을 찾았다. 하지만 memory leak등의 이슈로 anit pattern이라 한다. 그러나 테스트데이터만 빨리 만들면 되었기 때문에 일단 이 방법은 선택해서 진행하였는데 JAP에로 MOCK 데이터를 DB에 삽입할 때 알 수 없는 entity라는 오류가 발생한다. 또한 아래 작성한 코드의 예를 보듯 해당 클래스에 존재하지 않는 setter를 호출 해도 문제 없이 빌드가 되는 현상발생
그래서 {{...}}를 이용한 객체 초기화는 포기

남은 방법은 생성자를 이용하는 방법과 builder 패턴을 구현하는 방법

c#은 named parameter를 지원하기 때문에 모든 인자를 받는 생성자를 만들고 이름을 지정하며 객체를 생성하는 방법이 가능하지만
자바는 이를 지원하지 않아서 패스
결국 남은 방법은 builder 패턴 구현하는 방법 (c#에서 builder패턴을 구현 할때는 fluently하게 값을 세팅하고 싶으때 였는데 실무에서 많이 발생하는 일은 아님.)

lombok을 이용하여 쉽게 해결 할 수 있을 줄 알았는데 상속관계에서 lombok으로 builder를 구현하면 @SuperBuilder Annotation을 선언해야 하는데 intellj에서 "error: cannot find symbol @SuperBuilder" 오류가 발생한다. 꽤 오랜시간 원인을 찾으려 했지만 인터넷에 나와 있는 방법을 모두 해봤지만 해결 못했음.

결국은 손수 builder 패턴 구현

c#에서 작성한 코드양보다 3배는 더 많아짐 단순히 property만 선언하면 되는데 자바에서는 field 선언 getter, setter 구현
builder 패턴과 관련된 static inner class 선언과 내부 메서드 작성.

쓸데 없는데 시간을 너무 많이 써야 한다.

아래 코드는 왜 문제 없이 빌드 되는지 모르겠음

Code
public class Book {
    private String title;
    private BigDecimal price;

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

public class Autor {

    private String name;
    private int age;

    private List<Book> books;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    public List<Book> getBooks() {
        return books;
    }
}

public class Main {
    public static void main(String[] args) {

        Autor autor = new Autor() {{
            setName("paul");
            setAge(42);
            setBooks(List.of(
                    new Book() {{
                        setPrice(BigDecimal.valueOf(10000));
                        setTitle("my life");
                        //Book 클래스에는 setName이 없는데 문제 없이 컴파일 됨
                        //Author의 setName이 호출
                        setName("????");
                    }},
                    new Book() {{
                        setPrice(BigDecimal.valueOf(20000));
                        setTitle("your life");
                        setName("xxxx");
                    }}
            ));
        }};
    }
}

0개의 댓글