HihoBookStudy / EffectiveJava

이펙티브 자바 북스터디입니다.
1 stars 0 forks source link

[Item 50] Date.getTime() #42

Open zpqmdh opened 1 week ago

zpqmdh commented 1 week ago

p.306: 이전 버전의 자바를 사용한다면 Date 참조 대신 Date.getTime()이 반환하는 long 정수를 사용하는 방법을 써도 된다.

책에 수록된 Period 예제를 자바 8이상으로 개발할 때 Instant 혹은 LocalDateTime, ZonedDateTime을 사용하는 방법을 제시하며 다른 방법으로 위의 인용구를 제시하였습니다.

해당 방법을 적용하면 어떻게 코드를 수정할 수 있는지 보여주실 수 있나요?

ForteEscape commented 1 week ago

Q.

책에 수록된 Period 예제를 자바 8이상으로 개발할 때 Instant 혹은 LocalDateTime, ZonedDateTime을 사용하는 방법을 제시하며 다른 방법으로 위의 인용구를 제시하였습니다. 해당 방법을 적용하면 어떻게 코드를 수정할 수 있는지 보여주실 수 있나요?

A.

import java.util.Date;

public class Period {

    // 기존 코드에서의 start, end는 Date 객체였지만 getTime()을 사용할 경우 객체의 밀리세컨드 값을 저장합니다.
    private final long start;
    private final long end;

    public Period(Date start, Date end) {
        /*
        Date 객체를 그대로 사용하지 않고 내부의 밀리세컨드 long 값을 사용하므로 방어적 복사가 필요하지 않습니다.
        이때 생성자로 객체를 만든 뒤에 곧바로 매개변수로 들어온 Date 객체인 start 또는 end 값을 수정하더라도 이미
        long 값으로 복사가 완료되었기 때문에 현재 Period 에는 어떠한 영향도 끼칠 수 없습니다.
        추가적으로 매개변수로 들어온 start 또는 end 가 null 인 경우에도 getTime()을 수행하면서 NullPointerException 이 throw 되므로
        매개변수 검증에서 null 체크가 자동으로 되는 것도 확인할 수 있습니다.
         */
        this.start = start.getTime();
        this.end = end.getTime();

        /*
        compareTo 에서 양수가 된다는 것은 start 를 밀리세컨드로 변환했을 때 end 를 밀리세컨드로 반환한 것보다
        큰 상태를 의미하므로 다음과 같이 변경할 수 있습니다.
         */
        if(this.start > this.end) {
            throw new IllegalArgumentException("Start date cannot be greater than end date");
        }
    }

    /*
    Getter 함수에서도 방어적 복사를 수행하여 객체 값을 반환할 필요가 없습니다.
    이미 생성한 값이 long 이기 때문입니다.
     */
    public long getStart() {
        return start;
    }

    public long getEnd() {
        return end;
    }

    public static void main(String[] args) {
        Date startDate = new Date(2012, 1, 12);
        Date endDate = new Date(2014, 12, 12);

        try {
            Period period = new Period(startDate, endDate);

            System.out.println("수정 전 startDate의 millisecond : " + startDate.getTime());
            startDate.setYear(2015);

            System.out.println("period 의 start millisecond : " + period.getStart());
            System.out.println("수정된 startDate의 millisecond : " + startDate.getTime());
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
}

image