객체 재사용
•
동일한 기능의 객체를 매번 생성하여 사용하기보다는, 객체 하나를 재사용하는 편이 더 빠르고 세련된 방법일 수 있다.
•
특히 불변 객체는 언제든 재사용해도 동일한 결과를 얻을 수 있다.
String s = new String("bikini");
Java
복사
•
위와 같이 작성하게 되면 해당 문장이 실행될 때마다 String 인스턴스를 새로 생성하게 된다.
String s = "bikini";
Java
복사
•
이렇게 수정하면 매번 새로운 인스턴스를 만드는 대신, 하나의 String 리터럴 인스턴스를 사용하게 된다.
•
이와 같이 문자열 리터럴을 사용하는 모든 코드는 같은 객체를 재사용하는 것이 보장된다.
•
생성자 대신 정적 팩터리 메서드를 제공하면 불변 클래스를 제공하여 불필요한 객체 생성을 피할 수 있다.
•
Boolean(String) 생성자 대신 Boolean.valueOf(String) 팩터리 메서드를 사용하면, 생성자는 매번 새로운 인스턴스를 만들지만 팩터리 메서드는 재사용한다.
•
특히 생성 비용이 비싼 객체는 캐싱하여 재사용하길 권장된다.
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})$");
}
Java
복사
•
이와 같이 정규 표현식을 사용하는 경우에는, String.matches 메서드의 내부에서 정규표현식용 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.matcher(s).matches();
}
}
Java
복사
•
그러니 이와 같이 객체를 재사용하여 빈번히 호출되는 상황의 성능을 상당히 개선할 수 있다.
•
오토박싱(auto boxing) 또한 불필요한 객체를 만들어낸다.
•
오토박싱은 기본 타입과 그에 대응하는 박싱된 기본 타입의 구분을 흐려주지만, 완전히 없애주지는 않는다.
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= integer.MAX_VALUE; i++)
sum += i;
return sum;
}
Java
복사
•
이 프로그램은 불필요한 오토박싱을 반복해서 수행하느라 성능이 무척 느려진다.
•
연산을 할 때는 가급적 박싱된 기본 타입보다는 기본 타입을 사용하고, 의도치 않은 오토 박싱이 숨어들지 않도록 주의하자.
•
그렇다고 해서 객체 생성을 항상 피하려 하지는 말자.
•
아주 무거운 객체거나 생성 비용이 비싼 객체가 아닌 이상 단순히 객체 생성을 피하고자 객체 풀을 만들지 말자.
•
기존 객체를 재사용해야 한다면 새로운 객체를 만들지 말고, 방어적 복사를 통해 새로운 객체를 만들어야 한다면 기존 객체를 재사용하지 말자.