규칙 6. 불필요한 객체 생성을 피하라

규칙 5. 불필요한 객체는 만들지 말라

  • 변경 불가능(immutable) 객체는 언제나 재용사할수 있다.([규칙 15](#item15))

  • Bad Practice 코드는 실행될 때마다 String 객체를 만드는 쓸데없는 짓을 한다. loop 도는 만큰 String 객체를 생성한다. *Good Practices*는 실행할 때마다 객체를 생성하지 않고, 동일한 String 객체를 사용한다. 같은 가상머신에서 실행되는 모든 코드가 해당 객체를 사용한다([JLS, 3.10.5](https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5)).

    ```java
    for(int i = 0; i < 999999; i++) {
    	// Bad Practice
    	System.out.println(new String("test"));
    	// Good Practice
    	System.out.println("test");
    }
    ```
  • Static Factory Method([규칙 1](#item1))를 이용하면 불필요한 객체 생성을 피할 수 있다.

    ```java
    Boolean.valueOf(String)
    ```
  • 변경 가능한 객체이지만 변경할 일이 없다면 재사용한다.

    *AS-IS*
    ```java
    public class Person {
    	private final Date birthDate;
    	public boolean isBabyBoomer() {
    		Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    		gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
    		Date boomStart = gmtCal.getTime();
    		gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
    		Date boomEnd = gmtCal.getTime();
    		return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;
    	}
    }
    ```
    *TO-BE*
    ```java
    public class Person {
    	private final Date birthDate;
    private static final Date BOOM_START;
    private static final Date BOOM_END;
    static {
    	Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    	gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
    	BOOM_START = gmtCal.getTime();
    	gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
    	BOOM_END = gmtCal.getTime();
    }
    	public boolean isBabyBoomer() {
    		return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;
    	}
    }
    ```
    static initialzer을 하지않고 [lazy initialization](#item71) 기법을 사용할 수도 있다. 하지만, 추천하지 않는다. 구현이 복잡해질 뿐더러 *TO-BE*로 개선한 것 이상으로 성능을 높이기 어렵기 때문이다([규칙 55](#item55)).
  • 어댑터 TO-DO

  • JDK 1.5 이후, 쓸데없는 객체 생성하는 방법 추가 - autoboxing

    ```java
    public static void main(String[] args) {
    	Long sum = 0L;
    	for (long i = 0; i < Integer.MAX_VALUE; i++) {
    		sum += i;
    	}
    }
    ```
    `sum`이 `long`이 아닌 `Long`으로 선언되어 있기 때문에 더해질때마다 객체가 생성된다(2^31개 생성). 객체 표현형 대신 기본 자료형을 사용하고, 생각지도 못한 자동 객체화가 발생하지 않도록 유의하라.
  • 직접 관리하는 객체 풀을 만들어 객체 생성을 피하는 기법은 객체 생성 비용이 극단적으로 높지 않다면 사용하지 않는 것이 좋다.

    독자적으로 관리되는 객체풀을 만들면,
  • 코드의 복잡성

  • 메모리 요구량 증가

  • 성능 떨어짐: 사용해야할 상황 - 데이터베이스

  • 접속 비용이 큼

  • 라이선스 정책에 따라 연결 수가 제한될 수 있음

  • 규칙 39는 방어적 복사<sub>defensive copy</sub>에 관한 것.

    ```java
    // 방어적 복사 방법
    public Period(Date start, Date end) {
        this.start = new Date(start.getTime());
        this.end = new Date(end.getTime());
    }
    ```
  • 규칙 5: "재사용이 가능하다면 새로운 객체는 만들지 말라"

  • [규칙 39](#item39): "새로운 객체를 만들어야 한다면 기존 객체는 재사용하지 말라" 방어적 복사가 요구되는 상황에서 객체를 재사용하는 것은 (쓸데없이 같은 객체를 만드는) 비용보다 훨씬 높다는 것에 유의하자. 필요할 때 방어적 복사본을 만들지 못하면 버그나 보안 결함으로 이어진다. 쓸데 없는 객체들은 고작 코드 스타일과 성능에나 영향을 줄 뿐이다.