이펙티브 자바 3판 - 아이템 6. 불필요한 객체 생성을 피하라.

김대협·2023년 1월 3일
0

Effective Java 3rd

목록 보기
6/9

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

같은 기능의 객체를 매번 생성하여 사용하지말고 객체 하나를 재사용하는 편이 낫다.
특히 불변 객체는 언제든 재사용할 수 있다.

그렇지만 이번 아이템을 객체 생성은 비싸니 무조건 피해야 한다로 오해해서는 않된다.
실제로 리팩토링 과정에서 하나의 for 문을 가독성 향상을 위해 여러개로 나누기도 한다.

1) String 클래스는 Immutable 클래스로 인스턴스를 매번 만들어 사용할 필요가 없다.
생성자를 통한 생성으로 쓸데없는 String 인스턴스를 만들지 마라.
문자열 리터럴을 사용하는 모든 코드가 같은 객체를 재사용함이 보장된다. (String pool)

public class Strings {
    public static void doTest() {
        String hello = "hello";
        String hello2 = new String( "hello" ); // 권장하지 않는 방법
        String hello3 = "hello";

        System.out.println( hello == hello2 ); // false
        System.out.println( hello == hello3 ); // true
    }
}

2) 정적 팩터리 메서드를 제공하는 불변 클래스에서는 정적 팩터리 메서드를 사용하라.

public class Tests {
    public static void doTest() {
        String strTrue = "true";
        Boolean bool = new Boolean( strTrue ); // 권장하지 않는 방법 (deprecated in JDK 9)
        boolean bool2 = Boolean.valueOf( strTrue );
    }
}

3) 생성 비용이 비싼 객체는 캐싱하여 사용하라.

public class ExpensiveCaching {
    private static final String REGEX = "[0-9]";
    private static final Pattern PATTERN = Pattern.compile( REGEX );

    private static boolean isRomanNumeralSlow( String s ) {
        return s.matches( REGEX );
    }

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

    public static void doTest() {
        long start = System.nanoTime();
        final int LOOP_CNT = 100;
        for ( int i = 0; i < LOOP_CNT; ++i ) {
            isRomanNumeralFast( String.valueOf( i ) );
        }
        long second = System.nanoTime();
        for ( int i = 0; i < LOOP_CNT; ++i ) {
            isRomanNumeralSlow( String.valueOf( i ) ); // 권장하지 않는 방법
        }
        long end = System.nanoTime();

        System.out.println( "elapsed time of reuse: " + ( second - start ) + ", elapsed time of not reuse: " + ( end - second ) );
    }
}

4) 불필요한 Auto Boxing 과정을 피하라.

public class AutoBoxing {
    private static final long LOOP_COUNT = 1000;

    private static long sumWithPrimitive() {
        long sum = 0L;

        return sum( sum );
    }

    private static long sumWithWrapper() {
        Long sum = 0L;

        return sum( sum );
    }

    private static long sum( long sum ) {
        for ( long i = 0L; i < LOOP_COUNT; ++i ) {
            sum += i;
        }
        return sum;
    }

    public static void doTest() {
        long start = System.nanoTime();
        long priVal = sumWithPrimitive();
        long secondStep = System.nanoTime();
        long wrapVal = sumWithWrapper(); // 권장하지 않는 방법.
        long end = System.nanoTime();

        System.out.println( "primitive routine: " + priVal + ", elapsed time: " + ( secondStep - start ) + "ns." );
        System.out.println( "wrapper routine: " + wrapVal + ", elapsed time: " + ( end - secondStep ) + "ns." );
    }
}

© 2022.12 Written by Boseong Kim.
profile
기록하는 개발자

0개의 댓글