JAVA/이펙티브 자바 3

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

lovineff 2021. 4. 2. 11:25

기존 객체를 재사용해야 한다면 새로운 객체를 만들지 말것

단, 방어적 복사(불필요한 객체 생성을 하지 않음)에 실패하면 언제 터져 나올지 모르는 버그와 보안 구멍으로 이어 지지만,불필요한 객체 생성은 그저 코드 형태와 성능에만 영향을 준다.

 

String 예시

아래 코드가 반복문이나 자주 호출되는 메서드 내에 있으면 쓸데없는 String 인스턴스 수가 만들어진다.

String s = new Strin("test");

위 코드를 개선

String s = "test";

 

Boolean 예시

Boolean a = new Boolean("true");

// 팩터리 메서드로 객체를 재사용한다
Boolean b = Boolean.valueOf("true");

위와 비슷한 코드로 Long도 있으니, 직접 확인해본다.

 

 

정규 표현식을 사용한 예시

성능이 중요한 상황에서 반복해 사용하기엔 적합하지 않다.

Pattern은 입력받은 정규표현식에 해당하는 유한 상태 머신(finite state machine)을 만들기 때문에 인스턴스 생성 비용이 높다.

// 정규표현식용 Pattern 인스턴스는, 한 번 쓰고 버려져서 곧바로 가비지 컬렉션 대상이 된다
static boolean isRomanNumeral(String s) {
	return s.matches("긴~~~~ 정규 표현식");
}

// 성능을 개선하려면 필요한 정규표현식을 표현하는 (불변인) Pattern 인스턴스를 
// 클래스 초기화(정적 초기화) 과정에서 직접 생성해 캐싱해두고,
// 나중에 isRomanNumeral 메서드가 호줄될 때마다 이 인스턴스를 재사용한다.
public class RomanNumerals {
	private static final Pattern ROMAN = Pattern.compile("긴~~~~ 정규 표현식"); 
	
	static boolean isRomanNumeral(String s) {
		return ROMAN.matchers(s).matches();
	} 
}

객체가 불변하면 재사용해도 안전함이 명백하다.

 

불필요한 객체를 만들어내는 오토박싱 예제

오토박싱이란?

오토박싱은 프로그래머가 기본 타입과 박싱된 기본 타입을 섞어 쓸 때 자동으로 상호 변환해주는 기술

오토박싱은 기본 타입과 그에 대응하는 박싱된 기본 타입의 구분을 흐려주지만,완전히 없애주는 것은 아니다.

// 모든 양수의 총합을 구한다.
private static long sum() {
	// sum 변수를 long 이 아닌 Long으로 선언해서 
	// 불필요한 Long 인스턴스가 ong 타입인 i가 Long 타입인 sum에 더해질 때마다 생성된다.
	Long sum = 0L;
	for (long i = 0; i <= Integer.MAX_VALUE; i++){
		sum += i; 
	}
	return sum;
}
// 모든 양수의 총합을 구한다.
private static long sum() {
	// 박싱된 기본 타입보다는 기본 타입을 사용하여, 의도치 않은 오토박싱을 제거하여 성능을 향상시킨다.
	long sum = 0L;
	for (long i = 0; i <= Integer.MAX_VALUE; i++){
		sum += i; 
	}
	return sum;
}

위 예제에 대해서 실제 수행 결과 최대 20%까지 차이가 발생한것으로 확인했다.