[Effective Java] Item6 - 불필요한 객체 생성을 피하라

지구🌍·2023년 2월 12일
0

Effective Java 공부

목록 보기
2/12
post-thumbnail

불필요한 객체 생성을 피하라

Item6 시작해보자~! 불필요한 객체 생성을 피하라! 요리조리

String Pool 사용해라!

똑같은 기능의 객체를 매번 생성하기 보단 객체 하나를 재사용하는 편이 좋다.

String s = new String("지수 최고");

위의 코드는 실행될 때마다 String 인스턴스를 새로 생로 생성한다. 수 백만개 인스턴스 생성될 가능성 있다.

String s = "지수 최고";

위 코드는 매번 인스턴스를 생성하는 코드를 개선한 것이다.
String Constant Pool 영역에 리터럴 저장하고 존재하면 재사용, 없으면 해당 영역에 리터럴 추가하는 방식
문자열 캐싱하여 가져온다.

String Constant Pool : Java의 힙 영역에 존재하는 특수한 공간으로, 문자열 리터럴을 저장하는 용도

생성자 대신 정적 팩토리 메소드를 사용해라!

생성자는 호출할 때마다 완전 새로운 객체를 만든다!(무조건 새로운 걸 만듬!)
하지만, 정적 팩토리 메소드를 사용하면 불변 객체 뿐만 아니라 가변 객체까지도 사용중에 변경되지 않음만 보장한다면 재사용 가능하다.

Wrapper Class에서는 캐싱을 지원해주는 valueOf()라는 메소드가 존재한다.

public static void main(String[] args) {
        Integer item1 = new Integer(50);
        Integer item2 = new Integer(50);

        System.out.println(item1 == item2);

        Integer item3 = Integer.valueOf(50);
        Integer item4 = Integer.valueOf(50);

        System.out.println(item3 == item4); // true 1.8 이전

        Integer item5 = 50;
        Integer item6 = 50;

        System.out.println(item5 == item6);
 }


하지만 자바 1.8에서는 valueOf() 추가할 필요 없다!

생성 비용이 비싼 객체는 캐싱해라!

생성 비용이 아주 비싼 객체를 반복해서 사용해야한다면 캐싱하여 재사용하는 것을 권장한다.
책에 있는 예시가 아닌 다른 블로그에 괜찮은 예시가 있어서 테스트 해보았다.

public class Item6 {

    private static int[] cachingArray = new int[500000];

    public static void main(String[] args) {
        long beforeTime = System.currentTimeMillis();

        // 1. 캐싱을 했을 때
        for (int i = 0; i < 200000; i++) {
            cachingArray[i] = 1;
        }
        System.out.println("캐싱 했을 때 소요시간(s) : " + (System.currentTimeMillis() - beforeTime) / 1000);

        // 2. 캐싱을 하지 않았을 때
        beforeTime = System.currentTimeMillis();

        for (int i = 0; i < 200000; i++) {
            int[] nonCachingArray = new int[500000];
            nonCachingArray[i] = 1;
        }
        System.out.println("캐싱 안 했을 때 소요시간(s) : " + (System.currentTimeMillis() - beforeTime) / 1000);
    }
}

캐싱을 했을 때와 안했을 때의 소요시간 차이를 확인할 수 있다.
하지만, 가벼운 객체는 그냥 만드는 편이 좋다. 괜히 쓸데 없이 캐싱을 하려다가 코드도 복잡해지고 성능이 오히려 떨어질 수 도 있기 때문이다.! 참고 하기!

어뎁터 : 실제 작업은 뒷단의 객체에 위임하고, 자신은

오토박싱을 조심해라!

불필요한 객체를 만들어내는 또 다른 예는 오토박싱이다.

오토박싱(auto boxing) : 기본 타입, 박싱된 기본 타입을 섞어 쓸 때 자동으로 상호 변환해주는 기술

public class AutoBoxing {
    public static void main(String[] args) {
        long beforeTime = System.currentTimeMillis();

        // 1. auto-boxing 사용 O
        Long sum = 0L;
        for (long i = 0; i <= Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println("auto-boxing 했을 때 소요시간(s) : " + (System.currentTimeMillis() - beforeTime) / 1000.0);

        // 2. auto-boxing 사용 X
        beforeTime = System.currentTimeMillis();
        long sum2 = 0L;
        for (long i = 0; i <= Integer.MAX_VALUE; i++) {
            sum2 += i;
        }
        System.out.println("auto-boxing 안 했을 때 소요시간(s) : " + (System.currentTimeMillis() - beforeTime) / 1000.0);
    }
}


long을 Long으로 선언함으로써 오토박싱이 동작하여 불필요한 Long 인스턴스가 여러개 생성되는 상황.
소요시간 차이를 보면 알 수 있다.

박싱된 기본 타입보다는 기본 타입을 사용하고 의도치 않은 오토박싱을 주의해야 한다.


🎈귀중한 참고자료🎈
참고자료1
참고자료2

profile
일취월장 하며 성장! 중! 공부한 것을 기록하자(^∀^●)ノシ

0개의 댓글