ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쓸데없이 객체를 만들지 말자!
    카테고리 없음 2023. 4. 19. 09:56
    이펙티브 자바! 불필요한 객체는 만들지 말라. 동일한 객체는 필요할 때마다 만드는 것보다 재사용하는 편이 낫다. 변경 불가능한 객체는 언제나 재사용할 수 있다. 우리는 절대로 피해야 할 극단적 예를 들어보겠다.
    String s = new String("hello string");
    
    위의 코드는 쓸데 없는 짓이다. 만약 위의 문장이 loop나 자주 호출되는 메서드 안에 있으면 쓸데 없는 객체가 수십만개 수백만게 만들어 질것이다.
    String s = "hello string";
    
    위와 같이 하면 같은 가상머신에서 실행되는 코드는 동일한 String을 재 사용한다. String을 객체로 생성해서 쓸데 없는 짓을 하지 말자! 다음 코드를 보자
    class Person{
      private final Date birthDate;
    
      public Person(Date birthDate){
        this.birthDate = birthDate;
      }
    
      public boolean isBabyBoomer(){
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        calendar.set(1946, Calendar.JANUARY,1,0,0,0);
        Date boomStart = calendar.getTime();
        calendar.set(1965, Calendar.JANUARY,1,0,0,0);
        Date boomEnd = calendar.getTime();
        return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;
      }
    }
    
    
    해당 코드는 1946년과 1964년 사이에 태어난 사람이면 참을 반환 한다. 위에 보면 메서드가 호출 될 때마다 Calendar 한개 TimeZone한개 Date는 두개나 쓸데 없이 만들어 낸다. 효율적인 코드는 정적 초기화 블록을 통해 개선하는 것이 좋다.
    class Person{
      private final Date birthDate;
      public static final Date BOOM_START;
      public static final Date BOOM_END;
    
      public Person(Date birthDate){
        this.birthDate = birthDate;
      }
    
      static{
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        calendar.set(1946, Calendar.JANUARY,1,0,0,0);
        BOOM_START = calendar.getTime();
        calendar.set(1965, Calendar.JANUARY,1,0,0,0);
        BOOM_END = calendar.getTime();
      }
    
      public boolean isBabyBoomer(){
        return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;
      }
    }
    
    이렇게 개선된 클래스는 Person클래스가 생성될때 한 번만 만든다. JDK 1.5부터는 쓸데 없이 객체를 마들 새로운 방법이 더 생겼다. 오토박싱이라는 것인데 자바의 기본형과 그 객체 표현형을 섞어 사용할 수 있도록 해준다. 둘 간의 변환은 자동으로 이뤄진다. 코드를 보자
    Long startTime = System.currentTimeMillis();
    Long sum = 0L;
    for (long i = 0; i < Integer.MAX_VALUE; i++) {
      sum += i;
    }
    System.out.println(sum);
    System.out.println(System.currentTimeMillis() - startTime);
    
    위와 같이 Int의 모든 양의 정수 합을 계산하는 코드이다. 시간이 얼마나 걸릴까? 생각보다 많은 시간이 걸린다. Long으로 선언되어 쓸데 없는 객체들이 만들어 진다. 자료형을 Long에서 long으로 바꾸자 상당한 시간이 줄었다. 객체 표현형 대신 기본 자료형을 사용하고 생각지도 못한 자동 객체화가 발생하지 않도록 유의하라는 것이다. 그러나 객체를 만드는 비용이 높으니 무조건 피하라는 것은 아니다. 생성자 안에서 하는 일이 작고 명확하면 객체 생성과 반환은 신속하게 이루워진다. 잘 판단해서 쓰라는거 같다. 쓸데 없이 객체를 생성하지 말자!

    댓글

Designed by Tistory.