언어/Effective Java

이펙티브 자바 Item6 - 불필요한 객체 생성을 피하라

now0204 2024. 5. 27. 16:35

 

불필요한 객체 생성을 피하면서 자원을 절약해야한다.

같은 기능의 객체를 새로 생성하는 대신, 객체 하나를 재사용하는 편이 나을 때가 많다.

특히, 불변 객체는 언제든지 재사용할 수 있다.

 

같은 기능 수행하는 객체에 대한  재사용 강조

  • 싱글톤 사용 (내가 구현할 때)
  • static factory 메서드 사용 (구현된 것을 사용할 때)
  • 객체 캐싱 (무거운 객체일 때 미리 초기화 혹은 flyweight 패턴 고려) 
  • 같은 인스턴스 대변하는 여러 타입을 굳이 만들지 말 것 
  • 박싱 클래스는 꼭 필요한 경우만 사용

 


1. 문자열 객체 생성 

 

같은 값임에도 다른 래퍼런스인 경우 - 기존 인스턴스를 재사용하자 

 

문자열의 경우 항상 new 로 새로운 문자열을 생성하기 보다 같은 문자열이라면, "java"처럼 리터럴로 생성한다.

 

2. static factory 메서드 사용하기

 

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

생성자는 호출할 때마다 새로운 객체를 만들지만, 팩터리 메서드는 그렇지 않다.

ex Boolean(String)보다 Boolean.valueOf(String) 

 

3. 무거운 객체 

 

만드는데 메모리나 시간이 오래 걸리는 비싼 객체를 반복적으로 만들어야 한다면, 캐싱을 해두고 재사용할 수 있는지 고려해보는 것이 좋다.  

static boolean isRomanNumeralSlow(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 생성비용은 높은 클래스 중 하나이다. 
  • 만약 늘 같은 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 isRomanNumeralFast(String s) {
        return ROMAN.matcher(s).matches();
    }
}
  • 미리 만들어둔 Pattern을 matcher에 집어넣고 검사한다.
  • 이와 같이 생성비용이 비싼 객체는 "캐싱"을 적극 고려해봐야한다. (static final로 두고 재사용하자)

4. 같은 인스턴스를 대변하는 여러개의 인스턴스는 사용하지 않도록 한다.

 

  • 예를 들어 Map 인터페이스의 keySet함수를 들 수 있다.
  • keySet 메서드는 Set 인스턴스를 반환한다. 
  • 동일한 Map에서 호출하는 keySet메서드는 같은 Map을 대변하므로, Set인스턴스는 많을 필요가 없다. 

5. 오토박싱

  • 불필요한 박싱/언박싱은 불필요한 메모리 할당 재할당을 반복할 수 있다.
  • 꼭 박싱 타입이 필요한 경우가 아니라면 기본타입을 사용하자 

 

"객체 생성은 비싸니 피해야한다"로 오해하지 말자 

  • 일반적으로 작은 객체를 생성하고 회수하는 일에는 크게 부담이 없다.
  • 단순히 불필요한 객체 생성을 피하기 위해 flyweight패턴을 적용한 풀 같은걸 만들 필요는 없다.

 

재사용 vs 방어적 복사

  • 재사용할 수 있으면, 방어적 복사를 통해 사용하는 것 보단 그냥 재사용하는 편이 낫다 
  • 물론 상황에 따라 다르니 스스로 잘 판단하자 

참고자료 

https://velog.io/@lychee/%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C-%EC%9E%90%EB%B0%94-%EC%95%84%EC%9D%B4%ED%85%9C-6.-%EB%B6%88%ED%95%84%EC%9A%94%ED%95%9C-%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1%EC%9D%84-%ED%94%BC%ED%95%98%EB%9D%BC

 

[이펙티브 자바] 아이템 6. 불필요한 객체 생성을 피하라

불필요한 객체 생성을 피하면서 자원을 절약해야 한다.똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다.특히, 불변 객체는 언제든 재사용할 수 있다.이

velog.io

https://javabom.tistory.com/30

 

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

객체 생성이 잦은데 그 비용이 크다면? "불필요한 객체 생성을 피하면서 자원을 절약해야한다" 1. 같은 값임에도 다른 레퍼런스인 경우 같은 값을 가지고 동시에 불변객체라면 같은 레퍼런스를

javabom.tistory.com