만약 내가 새로 인스턴스를 습관적으로 새로 생성하려고 하는 상황이 있다고 생각해보자.
그럼 바로 new 생성자를 통해서 인스턴스를 생성할 것이 아니라, 내가 만드려고 하는 대상이 불변 클래스인지 아닌지 생각해보고, 그 클래스의 정적 팩터리 메서드를 사용할 수 있는지 생각해보자.
정적 팩터리 메소드를 사용하면 불필요한 객체 생성을 피할 수 있기 때문이다. Boolean을 생성자로 생성하는 것보다 Boolean.valueOf(String)이라는 팩토리 메소드를 사용하는 것이 좋다는 얘기다.
만약 생성비용이 비싼 객체라면 어떨까? 불필요한 생성을 줄임으로써 성능을 상당히 개선할 수 있을 것이다. 이런 비싼 객체가 반복해서 필요하다면 '캐싱'을 통한 재사용이 아주 유용할 수 있다.
static boolean isRomanNumeral(String s){
return s.matches // 이 메소드 안에서 pattern 인스턴스가 일회성으로 사용됨. 생성비용 높음.
("^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
위의 예시에서 사용되는 mathes메소드는 내부에서 Pattern 인스턴스를 생성한다. 이 인스턴스는 한 번 쓰고 버려져서 가비지 컬렉션 대상이 된다. 또한 입력받은 정규 표현식에 해당하는 유한 상태 머신(fininte state machine)을 만들기 때문에 인스턴스 생성 비용이 높다. 따라서 이 Pattern 인스턴스를 클래스 초기화 과정에서 직접 생성해서 캐싱을 해두고, 이 인스턴스를 재사용한다.
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 isRomanNumeralFast(String s) {
return ROMAN.matcher(s).matches(); // 인스턴스 재사용
}
불필요한 객체 생성1 - 어댑터
어댑터는 뷰(view)라고도 불리는데, 실제 작업은 뒷단 객체에 위임하고 자신은 제 2의 인터페이스 역할만 해주는 객체를 말한다.
예를들어 Map인터페이스의 KeySet 메소드는 매번 같은 set 인스턴스를 반환한다. 반환된 set 인스턴스가 만약 일시적으로 가변이더라도 반환된 인터페이스들은 기능적으로 모두 똑같다. 즉, 반환한 객체 중 하나를 수정하면 다른 모든 객체가 바뀐다. 모두가 똑같은 Map 인터페이스를 대변하기 때문이다. keySet이 매번 인스턴스를 새로 생성해서 set 인스턴스를 반환한다면 그것은 객체를 불필요하게 생성한다고 할 수 있을 것이다.
불필요한 객체 생성 2 - 오토박싱 (auto boxing)
오토박싱은 기본 타입과 그에 대응하는 박싱된 기본 타입의 구분을 흐려주지만, 완전히 없애주는 것은 아니다. 기능상의 문제는 없지만 성능에서는 그렇지 않다.
private static long sum() {
Long sum = 0L;
for( long i = 0 ; i < Integer.MAX_VALUE ; i++ ){
sum += i; // primitive 타입인 long -> Long으로 변환되면서 불필요한 Long 인스턴스 생성
}
return sum;
}
위의 예시처럼 오토박싱의 과정에서 약 6배의 성능 차이를 낼 수 있다. 그렇기 때문에 박싱된 기본타입보다는 기본 타입을 가용하고, 의도치 않은 오토박싱이 숨어들지 않도록 주의해야 한다.
'Reading > 이펙티브 자바' 카테고리의 다른 글
아이템9 . try-finally 보다는 try-with-resource를 사용하라 (0) | 2022.04.24 |
---|---|
아이템 7. 다 쓴 객체 참조를 해제하라 (0) | 2022.04.24 |
아이템3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2022.04.24 |
아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2022.04.24 |
아이템1. 생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2022.04.24 |