이펙티브 자바 아이템6 정리

이창호·2022년 4월 18일
0

이펙티브자바

목록 보기
8/12

String 인스턴스

아래 코드는 실행 될 때 마다 String 인스턴스를 새로 만든다.

	String rice = new String("kimchi");

아래 코드는 새로운 인스턴스를 만들지만 하나의 String 인스턴스를 사용한다.
이 방법은 문자열 리터럴 생성 방식으로 String Contstant Pool이란 영역에 저장된다.

	String rice = "kimchi";

String.maches()의 성능 이슈

아래 코드는 String.marches의 내부 코드다.
코드를 보면 matches를 사용 할 때마다 Pattern 인스턴스를 사용하고 버려진다.
이렇게 버려지면 가바지 컬렉션의 대상이 된다.

	//  ...의 내용을 토대로 Pattern 인스턴스가 생성된다.
	"".matches(...);
    
    public boolean matches(String regex) {
        return Pattern.matches(regex, this);
    }
    
    public static boolean matches(String regex, CharSequence input) {
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(input);
        return m.matches();
    }
    
    public static Pattern compile(String regex) {
        return new Pattern(regex, 0);
    }

아래 코드는 (불변인) Pattern 인스턴스를 정적 초기화 한다.
나중에 필요할 때마다 불러도 인스턴스를 재사용한다.

	private static final TEST_PATTERN = Pattern.compile(...);
    
    TEST_PATTERN.matcher("...").matches();

위와같이 불필요한 인스턴스를 생성하는 경우가 있을 수 있으니 한번은 내부 동작을 살펴보자.

지연초기화 (lazy initialization)

필드 초기화 시점을 그 값이 처음 필요할때까지 늦추는 기법이다.

synchronized를 활용하여 thread safe하게 초기화하는 기법,

정적 필드용 지연 초기화 홀더 클래스 관용구로 초기화하는 기법,

인스턴스 필드 지연 초기화용 이중검사 관용구 기법을 사용한다.

어댑터 (Adaptor 또는 View)

오토박싱 (auto boxing)

아래 코드와 같이 기본 타입과 래퍼 타입을 혼용해서 쓰면 오토박싱이 일어난다.
메서드 안의 sum 변수의 타입이 Long이라 sum += i를 수행할 때 마다 Long 인스턴스가 만들어 진다.

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

방어적 복사 (defensive copy)

방어적 복사는 List 같은 객체를 매개변수로 줬을 때, 메서드에서 사용 중
다른 스레드에서 해당 List 객체의 값을 변경하면 문제가 발생한다.

그렇기 때문에 매개변수로 넘겨줄땐, 새로운 객체를 생성해서 넘겨야 한다.

무거운 객체가 아니면 생성하는게 나을 수 있다.

JVM의 가비지 컬렉터는 잘 최적화 되어 있어서 DB 커넥션 풀 같은 무거운게 아니면 생성하는게 나을 수 있다.

방어적 복사를 실패했을 때 일어나는 문제가 객체 반복 생성을 했을 때의 피해보단 훨씬 크다.

profile
이타적인 기회주의자

0개의 댓글