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

불필요한 객체 생성의 예시

생성자를 통한 String의 할당

  • String은 보통 인스턴스를 생성할 때 “문자열” 형태로 초기화함

  • 이는 String constant pool을 통해 정확히 동일한 문자열은 재사용하기 위함

  • 그러나 new String(”문자열”)을 통해 할당하면 단순히 “문자열”을 통해 할당한 것과 정확히 동일한 동작을 함에도, 새 객체를 생성하게 됨

생성자를 통한 Wrapper의 할당

  • wrapper 또한 valueOf 메소드를 통해 할당할 것을 권장하는데, 이는 생성자를 통해 생성하면 무조건 새 객체가 생성되지만 valueOf를 통해 생성하면 캐싱을 이용해 특정 범위 내 객체는 재사용이 가능하기 때문

    • Java 9부터는 Wrapper 클래스의 생성자가 deprecated 되었음

  • 이는 Item 1과 연관지어, 정적 팩토리 메서드를 사용하는 경우 생성자와 달리 반드시 새 객체를 반환할 필요가 없는 것의 이점을 보여주고 있음

Wrapper의 무분별한 사용에 의한 빈번한 오토 박싱

public long sum(long max) {
		Long sum = 0L;
		for (long i = 0; i <= max; i++) {
			sum += i;
		}
}
  • 위의 코드는, 단순히 sum을 long이 아닌 Long으로 선언했기 때문에 심각한 비효율을 초래

  • sum += i 연산이 이루어질 때마다 새로운 Long 인스턴스가 생성됨

언제 객체를 재사용?

  • 불변임이 확실할 때 캐싱을 통해 반복해서 재사용

  • 생성 비용이 비싼 객체는 Pool을 통해 사용 후 회수하는 방식으로 재사용

    • Connection Pool, Thread Pool과 같은 것이 이에 해당

    • 하지만 Pool 방식은 코드 복잡도를 증가시키고, 메모리 사용량을 늘리기 때문에(미리 여러 객체를 선언해 가지고 있는 것이므로), 비용이 비싼 객체에만 적용해야 함

    • 최근 JVM의 GC는 가벼운 객체를 다루는 것에 큰 부담을 느끼지 않음

재사용을 조심할 것

  • 재사용할 수 있는 것을 재사용하지 않았을 때에 발생하는 것은 성능 이슈

  • 재사용할 수 없는 것을 재사용했을 때에는 버그보안 취약점이 발생 가능

  • 따라서 객체를 재사용하고자 할 때에는 정말로 재사용이 가능한 경우에 해당하는지 신중하게 결정해야 함

Last updated