본문 바로가기

Reading Record/이펙티브자바

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

객체 생성이 잦은데 그 비용이 크다면?

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

 

 

1. 같은 값임에도 다른 레퍼런스인 경우

같은 값을 가지고 동시에 불변객체라면 같은 레퍼런스를 가져야한다.

다시말해, 같은 값을 가지는 인스턴스가 두 개 이상 만들어 지는 것은 "불필요한 객체생성"이다.

 

대표적인 불변클래스 String 을 예로들면,

String 클래스는 같은 문자열이라면 같은 레퍼런스를 지닌다. 

 

두 객체가 같은 레퍼런스를 참조한다

그런데 만약 String s = new String("String") 방식으로 스트링 객체를 생성한다면, 이후에 String s2 = new String("String") 시에 같은 문자열임에도 다른 레퍼런스를 가지게 된다. 

 

이렇게 쓰지 말라고 회색처리도 해준다.

 

 

 

2. 재사용 빈도가 높고 생성비용이 비싼 경우

 

생성비용이 비싼 객체라면 "캐싱" 방식을 고려해야한다.

자주쓰는 값이라면 static final 로 초기에 캐싱해놓고 재사용하자.

 

위 코드의 Pattern은 생성비용이 높은 클래스 중 하나이다.

만약 늘 같은 Pattern 이 필요함이 보장되고 재사용 빈도가 높다면 위와 같이 상수로 초기에 캐싱해서 재사용 할 수 있다.

 

 

 

필드 캐싱과 관련해 나온 개념)
지연초기화를 통해 자주 호출되지 않는 필드를 처음 호출될 때 초기화할 수 있지만,  코드를 복잡하게하고 성능이 크게 개선되지 않기 때문에 권장하지 않는다. (http://wonwoo.ml/index.php/post/724)

 

 

 

3. 같은 인스턴스를 대변하는 여러개의 인스턴스를 생성하지 않도록

ex) Map 인터페이스의 keySet 함수

keySet 메서드는 Set 인스턴스를 반환한다. 하지만 동일한 Map 에서 호출하는 keySet 메서드는 같은 Map 을 대변하기 때문에 거기서 생성되는 Set 인스턴스들은 결국 동일한 Map 을 대변할 뿐이다. 

 

javabomSet1, javabomSet2 는 모두 같은 Map 의 key Set 을 반환한다.

따라서 불필요하게 할당할 필요가 없다. 

 

+ 참고로 여기서 Set 인터페이스와 Map 인터페이스를 연결하는 keySet 메서드를 어댑터라고한다. 어댑터 패턴을 다음 포스팅을 참고하자.(https://niceman.tistory.com/141)

 

 

 

4. 오토박싱 

불필요한 박싱/언박싱은 불필요한 메모리 할당, 재할당을 반복할 수 있다.

꼭 박싱 타입이 필요한 경우가 아니라면 기본타입을 사용하도록 하자.