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

일고잉·2021년 7월 24일
0

같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 것이 좋을 때가 많다. 재사용은 빠르고 세련되다. 특히 불변 객체는 언제든 재사용할 수 있다.

생성자 대신 정적 팩터리 메서드를 제공하는 불변 클래스에서는 정적팩터리 메서드를 사용해 불필요한 객체 생성을 피할 수 있다.

new Boolean("true");
// 위(생성자) 대신 아래 코드를 사용한다
Boolean.valueOf("true");

생성 비용이 비싼 객체가 있으면 재사용하자

다음과 같은 예시가 있다.

static boolean isRomanNumeral(String s){
	return s.matches("^(?=.)M*(C[MD]|D?C{0,3}"
    		+ "((X[CL]|L?X{0,3})(I[XV]|v?I{0,3})$";
}

String.matches()의 Pattern 인스턴스는 한 번 쓰고 버려지는데, Pattern은 입력받은 정규표현식에 해당하는 유한 상태 머신을 만들기 때문에 인스턴스 생성 비용이 높고, 그래서 그 객체를 재사용해서 성능을 개선할 수 있다고 한다.

// 성능 개선
public class RomanNumerals{
	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 isRomanNumeral(String s){
		return ROMAN.matchers(s).matches();
	}
}

오토박싱으로 인해 불필요한 객체가 생성되지 않도록 하자

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

Long 타입의 sum 변수에 i를 더할 때마다 오토박싱으로 인해 불필요한 Long 인스턴스가 생성된다. 그래서 제대로 짠 코드보다 훨씬 느리다.
sum 변수를 long 타입으로 바꾸자. 저자는 Long을 사용할 때보다 실행 시간이 10배 빨라졌다고 한다.

불필요한 객체 생성을 피한 예

Map인터페이스의 keySet 메서드가 반환하는 Set객체를 보면 알 수 있다.
이 코드를 실행하면 keySet2에서 1이 사라진 것을 알 수 있다.

Map<Integer, String> map = new HashMap<>();
map.put(1,"one");
map.put(2,"two");
map.put(3,"three");
Set<Integer> keySet1 = map.keySet();
Set<Integer> keySet2 = map.keySet();
keySet1.remove(1);
for (int i : keySet2){
	System.out.println(i);
}

0개의 댓글