본문 바로가기

STUDY/이펙티브자바

2-6) 불필요한 객체 생성을 피하라

불필요한 객체 생성

 

 

같은 내용을 가지는 객체를 여러개 생성하는 것은 메모리상의 낭비를 가져온다. 현재는 같은 속성 값을 가지고 있지만 추후 달라질 수 있는 객체라면 필요에 따라서 객체를 중복 생성할 수 있다. 하지만 그것이 아니라면 불필요한 객체 생성을 피하고 하나의 객체를 재사용하는 것이 옳다.

 

// 지금은 같아 보일지라도 개명할 수 있으니, 객체를 각자 생성한다.
String name1 = new String("이기수");
String name2 = new String("이기수");

// 한국은 언제나 한국이다, 객채를 재사용하는것이 옳다.
String born_country = new String("한국");
String cur_country = new String("한국");

 

// 메소드가 호출될 때 마다 Pattern 객체가 생성된다.
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})$");
}

// 미리 생성해둔 Pattern 객체를 재사용 하여 6.5배의 성능이 향상되었다.
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();
}

 

 


주의사항

 

객체를 재사용하면 메모리와 성능상의 이점을 기대할 수 있다. 하지만 그 반대로 조심해야될 내용도 있다. 객체를 재사용한다는 것은 하나의 객체를 여러곳에서 동시에 사용한다는 뜻이다. 이 내용을 주의해서 개발을 하지 않으면 코드가 뜻하지 않게 동작할 수 있다. 

 

// list 객체와 멀티스레스 환경에서도 안전한 synchronizedList 객체를 생성하였다.
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
List<Integer> synchronizedList = Collections.synchronizedList(list);

// list를 clear 했는데 synchronizedList의 요소도 모두 사라졌다. synchronizedList가 list객체를 재활용 하기 때문이다.
list.clear();
System.out.println(synchronizedList);

 

 


오토박싱

 

// 1은 기본적으로 int 이지만 오토박싱 덕분에 Integer인 num으로 대입된다.
Integer num = 1;

 

불필요한 객체를 만들어내는 또 다른 예로 오토박싱이 있다. 오토박싱은 필요에 따라 자바의 기본 타입(int, long, char 등)을 참조 타입(Integer, Long, Character 등)으로 바꾸어주는 것을 말한다. 오토 박싱이 없다면 기본 타입과 참조 타입이 함께 사용될 때 일일이 변환을 해주어야 했을 것이다.

 

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

위 코드에서는 long 타입인 i와 Long 타입인 sum을 더해줄 때 오토박싱이 일어난다. 오토박싱 때문에 계속 new Long(i)로 Long 객체가 생성되고 프로그램에 불필요한 부하가 걸린다. 여기서 sum의 타입을 Long에서 long으로 바꾸어주기만 해도 대략 6배의 성능 향상이 이루어진다.

 

 


오토박싱이 나온김에 오토언박싱에 관련된 재밌는 이슈를 공유한다.

 

class Main {
    public static void main(String[] args) {
        // 1. 참조타입에 null값 대입
        Long a = null;

        // 2. 삼항 연산자 수행
        // 조건이 false 이기 때문에 a가 b에 대입
        Long b = false ? 0L : a;
    }
}

[자바] 삼항 연산자에서 Null Pointer Exception이 발생한다고?

728x90