아이템 6. 불필요한 객체 생성을 막아라.
똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 특히 불변 객체는 언제든 재사용할 수 있다.
실행될 때 마다 인스턴스를 새로 만드는 다음과 같은 예제는 절대 추천하지 않는다. 우리는 첫번째 코드 대신, 개선된 두번째 코드를 통해 생성되는 인스턴스의 수를 줄일수도 있을 뿐만 아니라 모든 코드가 같은 객체를 사용함을 보장할 수 있다.
String s = new String("joanne"); // NOPE !
String s = "joanne"; // BETTER
우리가 아무렇지 않게 사용하는 객체 중에는 생성 비용이 아주 비싼 객체도 더러 있다. 그것은 바로바로! Pattern 객체이다.
Pattern 인스턴스는 입력받은 정규 표현식에 해당하는 유한 상태 머신을 만들기 때문에 인스턴스 생성 비용이 매우 높다. 따라서 성능을 개선하기 위해서는 필요한 정규표현식을 표현하는 불변 Pattern 인스턴스를 정적 초기화 과정에서 직접 생성해 캐싱해두고, 나중에 해당 메서드가 호출될 때마다 이 인스턴스를 재사용하도록 하는 방법이 가장 적합하다.
아래는 내가 우테코 코드리뷰를 진행하며 리뷰어분께 받은 피드백의 일부이다.
코드 내부에서 Pattern을 작성해두었기 때문에, 해당 메서드가 실행될 때 마다 패턴이 새롭게 생성된다.
하지만 나는 첫번째 피드백을 이해하지 못하고.. 매직넘버를 상수화하듯이 패턴도 static final로 필드에 추가하여 다시 재 리뷰를 요청했다.
private static final String PATTERN = "//(.)\n(.*)";
하지만 패턴 자체는 String이 아닌 Pattern 객체로 미리 생성해둘 수 있다.
패턴과 더불어, 박싱된 기본 타입보다는 기본 타입을 사용하고, 의도치 않은 오토박싱이 숨어들지 않도록 주의한다면 더 나은 코드를 작성할 수 있다. 책에서 발췌한 다음 코드 예제를 보자. 이 코드는 sum 변수를 long이 아닌 Long으로 선언함으로서 불필요한 Long 인스턴스가 약 2^31개나 만들어진다. (long 타입인 i가 sum에 더해지는 모든 순간마다 생성된다 😞)
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++){
sum += i;
}
return sum;
}