item6) 불필요한 객체 생성 지양
불필요한 객체 지양
똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용할 수 있도록 한다.
불변 객체는 언제든 재사용 가능하다.
정적 팩토리 메서드 사용
매번 새로운 객체를 만드는 생성자와 달리 불필요한 객체 생성을 피할 수 있다.
불변 객체뿐만 아니라 가변 객체도 사용 중 변경이 없다 판단되면 재사용이 가능하다.
생성 비용이 비싼 경우 객체 캐싱
아래와 같이 직접 matches를 사용할 경우 매번 Pattern 인스턴스가 새로 생성된다.
아래와 같이 Pattern final 객체를 선언해두면 반복해서 match()할 때 인스턴스를 재사용하도록 캐싱할 수 있다.
코드의 의미도 훨씬 잘 드러난다.
Pattern 객체는 입력받은 정규표현식에 대한 유한 상태 머신을 만들기 때문에 인스턴스 생성 비용이 높다.
어댑터(View)
어댑터
실제 작업은 뒷단 객체에 위임하고 제2의 인터페이스 역할을 해주는 객체
뒷단 객체만 관리하면 되므로 뒷단 객체 하나 당 하나만 만들어지면 충분하다.
불변 객체를 사용해 재사용을 하는 것이 일반적이지만, 덜 명확할 수도 있고, 이러한 직관에 반대되는 상황이 있을 수도 있다.
예시
Map.keySet()
은 Map의 key를 모두 담은 Set 뷰 인스턴스를 반환한다.Set 인스턴스는 가변 객체이지만 뒷단 객체 하나 당 하나만 만들어지면 충분하다.
동일한 Map에서 keySet() 메서드를 여러번 호출 시 같은 인스턴스를 반환하여, 반환한 객체 중 하나를 수정하면 다른 모든 객체가 따라서 바뀐다.
오토박싱
프로그래머가 기본 타입(int, long, ...)과 박싱된 기본 타입(Integer, Long, ...)을 혼용할 때 자동으로 상호 변환해주는 기술
기본 타입과, 그에 대응되는 박싱된 기본 타입의 구분을 흐려주지만 완전히 없애지는 않는다.
박싱된 기본타입을 사용할 경우 매번 새로운 인스턴스가 생성되기 때문에 성능이 저하될 수 있다.
박싱된 기본 타입보다는 기본 타입을 사용하고, 의도치 않은 오토박싱이 발생하지 않도록 주의할 것
객체 풀 구현
객체 생성을 피하고자 직접 객체 풀을 구현하는 방법이 있다.
일반적으로 코드를 헷갈리게 만들고, 메모리 사용량을 늘리고, 성능을 떨어뜨린다.
JVM의 Garbage Collector는 잘 최적화되어 가벼운 객체를 다룰 때에는 객체 풀보다 빠르다.
재사용 vs 방어적 복사
불필요한 객체 생성했을 때의 피해보다 (item50) 방어적 복사가 필요한 상황에서 객체를 재사용했을 때의 피해가 훨씬 크다.
불필요한 객체 생성은 코드 형태와 성능에만 영향을 주지만, 방어적 복사에 실패하면 버그와 보안 피해가 언제 발생할 지 모른다.
Last updated