Effective Java. 불필요한 객체의 생성을 피하자

Jae·2024년 3월 3일

Effective Java

목록 보기
6/11

개인적으로 객체를 계속해서 생성하는 것보다 재사용하는 것을 선호하는 편인데, 왜 그렇게 사용하는지에 대한 나름의 근거가 없었다. 마침 책의 챕터에서 설명을 해주고 있어서 흥미롭게 읽은 부분

객체의 재사용시 장점

  • 객체 생성에 소요되는 시간과 자원이 절감되어 속도가 빨라지고 가독성 좋은 코드의 작성이 가능하다.
  • 불변객체를 사용한다면 항상 재사용이 가능하다.

불변 클래스의 불필요한 객체 생성 막기

  • 객체 생성시 생성자를 이용해서 만들기보다 static 팩토리 메서드를 이용해서 만들기.

  • 생성자는 호출될 때마다 새 객체를 만드는데 static 팩토리 메서드는 객체를 새로 만들지 않는다.

  • new를 이용해서 객체를 생성하게 되면 항상 새로운 객체(메모리)를 만들게 되기에 인스턴스를 재사용하는 방법도 있다.

new 이용

String str = new String("hello");

인스턴스 재사용

String str = "hello";

가변객체의 경우라면 미리 static 초기자를 사용해서 비효율적인 객체 생성 막기

  • 인스턴스를 재사용함으로써 성능 향상이 가능하다.
  • 가독성도 좋아짐.
    ex. calender/date class

재사용여부가 불분명한 경우

어댑터 설계 패턴의 경우라고 할 수 있는데, 어댑터 패턴에 대해 간략하게 설명하자면, 다른 클래스에서 기존의 클래스를 재사용하려고 할 때, 둘 간의 인터페이스가 다를 경우 기존의 클래스를 변경하지 않고 함께 동작시키기 위한 어댑터 클래스를 만드는 것을 의미한다.
어댑터는 클라이언트 클래스(다른 클래스)에 기능을 위임하는 객체로써 클라이언트 클래스가 선택하여 사용하도록 제공한다.
특정 클라이언트 객체에 대한 것을 제공하기 때문에 어댑터 인스턴스는 특정 클라이언트 객체에 대한 인스턴스를 하나 이상 제공할 필요가 없다. (하나에 하나만 제공?!)

ex. map 인터페이스

오토박싱

기본형 데이터를 박스형으로 변환해주는 것.
단순한 연산을 위해 사용한다면, 불필요하게 참조 타입까지 생성될 수 있기 때문에 의도치 않은 오토박싱이 생기지 않도록 주의

private long sum() {
	Long sum = 0L;
    for(long i = 0; i <= Integer.MAX_VALUE; i++){
    	sum += i;
    }
    return sum;
}

이 과정에서 불필요한 객체가 2^31개 생겼다...

객체 풀을 직접 만드는 경우

DB connection 같은 경우에는 연결 비용이 높다. 그리고 일정한 수의 연결로 제한할 수 있다. 이런 경우엔 재사용하는 것이 아주 좋은 예가 된다.
단, 우리가 관리하기에 코드 작성이나 메모리 관리가 어려워서 JVM이 가비지 컬렉터 고도화하며 최적화 관리를 잘 해준다.

주의할 점 : 방어복사

새로운 것을 생성해야한다면 기존 객체를 재사용하지 말자.
방어복사에 실패하면 찾기 어려운 잠재적인 결함이 생길 수 있는 대신, 불필요한 객체 생성은 코드 구성 형태나 성능에만 영향을 주기 때문이다.

참고

effecitive java

0개의 댓글