[이펙티브 자바.아이템6] 불필요한 객체 생성을 피하라

박상준·2024년 5월 22일
0

이펙티브 자바

목록 보기
6/16

개요

  • 똑같은 기능의 객체를 매번 생성하기보다, 객체 하나를 재사용하는 것이 낫다.

잘못된 예시

  • 불필요한 객체의 생성
    String s = new String("psj") // 안좋음 --
    • 해당 코드의 경우 실행될 때마다 새로운 String 인스턴스를 만든다.
  • 개선
    String s = "psj"; //조음
    • 전자의 예시의 경우 매번 새로운 인스턴스를 만든다.
    • 대신 해당 예시의 경우 하나의 String 인스턴스를 재사용한다.
    • 같은 가상 머신(JVM 등) 안에서 이와 똑같은 문자열 리터럴을 사용하는 모든 코드가 같은 객체를 재사용함이 보장된다.

정적 팩토리 메서드의 사용

  • 생성자 대신 정적 팩토리 메서드를 사용하는 경우 불필요한 객체 생성을 피할 수 있다.
  • 사용자를 믿지마라.
  • 최대한 재사용하도록 유도해야한다.
Boolean b = Boolean.valueOf("true")

같이 Boolean(String) 생성자 대신 Boolean.valueOf(String) 팩토리 메서드를 사용함으로 새로운 객체를 만들지 않고 재사용이 가능하다.

public class BooleanCheck {

    public static void main(String[] args) {
        Boolean a = new Boolean(true);
        Boolean d = new Boolean(true);

        Boolean b = Boolean.valueOf(true);
        Boolean c = Boolean.valueOf(true);

        System.out.println(a == d); // false
        System.out.println(b == c); // true
    }
}
  • 를 출력하게된다.
  • b 와 c 는 결국 같은 인스턴스인 것이다.

성능이 중요한 순간에..

생성 비용이 비싼 객체는 캐싱하여 재사용하는 것이 좋음.

  • 잘못된 예시
    static boolean isRomanNumeral(String s) {
        return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
    }
    • "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$" 같은 정규표현식 문자열이 계속적으로 사용되는 경우는 비효율적입니다.
    • String.matches 메서드가 내부적으로 매번 새로운 Pattern 인스턴스를 생성하기에, 성능 저하가 우려된다.
  • 개선된 예시
    public class RomanNumerals {
        private static final Pattern ROMAN = Pattern.compile(
            "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$"
        );
    
        static boolean isRomanNumeral(String s) {
            return ROMAN.matcher(s).matches();
        }
    }
    • Pattern 객체를 재사용하는 것을 막기위해, Pattern 을 미리 static 으로 올려놓고 재사용하도록 합니다!

불필요한 객체생성 관련 예시

  • 오토박싱 문제
    • 기본 타입과 박싱된 기본 타입을 자동으로 상호 변환해주는 기술

    • 성능에 영향을 줄 수 있음.

      private static long sum() {
          Long sum = 0L;
          for (long i = 0; i <= Integer.MAX_VALUE; i++)
              sum += i;
          return sum;
      }
    • for 문 안에서 불필요한 Long 인스턴스를 약 2^31개나 만들어낸다..

    • 개선한다면?

      private static long sum() {
          long sum = 0L;
          for (long i = 0; i <= Integer.MAX_VALUE; i++)
              sum += i;
          return sum;
      }
      • 이렇게 생성한다면, 9초 → 0.66 초 까지 단축이 가능하다고 한다.
      • 왠만하면 기본타입을 사용하는 것을 기본으로 삼자.
profile
이전 블로그 : https://oth3410.tistory.com/

0개의 댓글