[아이템 6] 불필요한 객체 생성을 피하라

ajufresh·2020년 3월 4일
0

Effective Java 3/E

목록 보기
6/9
post-thumbnail

블로그에 게시하는 위 글은 전체적인 내용 정리가 아닌
책을 읽으면서 새로 알게된 내용이나 제가 중요하다고 생각하는 내용을 정리한 글입니다.

코드는 깃허브에 있는 코드를 사용했습니다.

객체의 재사용

같은 기능을 가진 객체를 새로 생성하는 것 보다는 재사용하는 편이 나을 때가 있다.

// 나쁘다
String s = new String("hello!");
boolean b = new Boolean("ha2");

// 좋다
String s = "hello!";
boolean b = Boolean.valueOf("ha2");

비싼 객체의 재사용

이외에도 비싼 객체를 재사용하는 것도 중요하다.
아래 코드를 보자

// (반복해서 사용할 경우에 효율이) 나쁘다
static boolean isRomanNumeralSlow(String s) {
        return s.matches("^(?=.)M*(C[MD]|D?C{0,3})" 
                + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}

matches() 메소드 안에서 생성하는 Pattern은 한 번 쓰고 버려지기 때문에 재사용이 불가능하다.
차라리 불변 Pattern 인스턴스를 직접 생성한 후에 캐싱해두고 재사용하는게 효율이 좋다.
-> 불변으로 생성하면 안전하게 재사용이 가능하기 때문이다.

// (반복해서 사용할 경우에 효율이) 더 낫다
 private static final Pattern ROMAN = Pattern.compile(
            "^(?=.)M*(C[MD]|D?C{0,3})"
                    + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    static boolean isRomanNumeralFast(String s) {
        return ROMAN.matcher(s).matches();
    }

하지만 가벼운 객체 같은 경우에는 그냥 만드는게 낫다.
오히려 자신만의 객체 풀을 만들면 코드를 헷갈리게 하고 메모리 사용량을 늘리고 성능을 떨어뜨리는 경우도 발생한다.

불필요한 객체 만들지 않기

오토박싱

reference type과 primitive type을 섞어 쓸 때 자동으로 상호 변환해주는 기술

private static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++)
        sum += i;
    return sum;
}

여기서 문제는 sum을 long이 아닌 Long으로 선언했다는 것이다.
(저 코드에서 long으로 바꾸면 6.3초 -> 0.59초가 된다.)

참조 타입(reference type)보단 기본 타입(primitive type)을 쓰는게 좋다.
만약 reference type을 사용하는 경우가 있다면, 의도치 않은 오토 박싱이 들어가지 않게 주의해야한다.


하지만 방어적 복사(아이템 50)가 필요한 상황에서는 절대 객체를 재사용하면 안된다.
실패하면 버그와 보안 구멍으로 이어지기 때문이다.

profile
공블로그

0개의 댓글