본문 바로가기
Java/Effective Java

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

by setung 2021. 12. 21.

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

무거운 객체라면 매번 생성할 때마다 많은 자원이 들어갈 것이고, 인스턴스를 자주 생성하게 되면 GC가 동작하게 될 확률이 높아진다.(GC는 애플리케이션 성능을 저하시키는 요인 중 하나)

 

String s = new String("hi");
String s = "hi";

String s = new String("hi");

정확하진 않지만 "hi"라는 문자열은 리터럴 스트링 풀에 저장이 될 것이고, new String()을 호출할 때마다 heap 영역에 String 인스턴스가 저장이 된다.

 

String s = "hi";

String pool에 "hi" 문자열이 저장이 되고, "hi"를 생성할 시 String pool에 있는 "hi"를 재사용하게 된다.

public static void main(String[] args) {
    String s = new String("hi");
    String s2 = new String("hi");
    String s3 = "hi";
    String s4 = "hi";
    
    System.out.println(s==s2);      // false 출력
    System.out.println(s3==s4);     // true 출력
}

간단 예제로 s와 s2는 참조값이 다르다는 것을 알 수 있고, s3와 s4는 같다는 것을 알 수 있다.

즉 s와 s2는 독립적인 메모리 공간을 차지하고 있다는 의미이다.

 

 

오토 박싱을 조심해야 한다.

자바에서 지원하는 매퍼 클래스는 일반 데이터 타입처럼 사용할 수 있도록 지원한다.

하지만 지원만 할 뿐 내부 동작 방식은 완전히 다르다.

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

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

    return sum;
}

두 함수의 차이는 sum의 타입이 Long과 long의 차이이다.

Long 매퍼 클래스에 연산이 될때마다 새로운 Long 인스턴스가 Heap에 저장이 된다.

실제 내 pc 기준으로 연산 속도가 10배정도 차이가 난다.

 

 

무거운 객체가 아니라면 객체 생성을 피하고자 굳이 객체 풀을 만들 필요가 없다.

요즘의 JVM의 GC는 최적화가 잘되어 있어 객체풀을 만들어 사용하는 것보다 객체 생성을 직접 하는 것이 더 좋을 수 있다.

댓글