본문 바로가기

IT/이펙티브자바 3E

[Effective Java] 아이템 6. 불필요한 객체 생성을 피하라.

안녕하세요 남갯입니다


오늘은 이펙티브 자바 item 6에 대해 포스팅 해보려고 합니다.



아이템 6. 불필요한 객체 생성을 피하라. 


String 관련 글에서도 작성했었지만 아래와같이

String s = new String("bikini"); 

이렇게 생성할 경우 매번 힙영역에 올라가게 됩니다.


아래의 글을 참조해주세요


2019/12/08 - [IT/Java언어] - [Java] String, StringBuilder, StringBuffer 란?



String s = "bikini" 를 통해 생성해서 상수풀에 올라가게 되므로 모든 코드가 똑같은 객체를 재사용함을 보장한다.




Boolean(String) // deprecate in java9 

생성자 대신 

Boolean.valueOf(String) 팩터리 메서드를 사용하는게 좋다.


boolean isRomanNumeral(String s){

return s.matches(....)

}



위의 메소드는 정규표현식을 통해 숫자인지 확인하는 부분인데, 이 메서드는 String.matches 메소드를 사용한다는곳에 있다. String.matches는 정규표현식으로 문자열 형태를 확인하는 가장 좋은 방법이지만 성능이 중요한 상태에서 반복해서 사용하기에는 적합하지 않음.


인스턴스를 매번 생성하지 말고, 자주 사용 할 경우 캐싱을 이용해라. 

Pattern 인스턴스는 한번 쓰고 버려져서 GC대상이 된다. 따라서 Pattern이라는 정적 초기화 과정에서 직접 캐싱하고 나중에 isRomanNumeral 메서드가 호출될 때 마다 인스턴스를 재사용한다.


public class RomanNumerals {

private static final Pattern ROMAN = Pattern.complile("....");

}



boolean isRomanNumeral(String s){

return ROMAN.matchers(s).matches();

}


위와같이 개선이 가능하다.


위와같이 만듦으로써 6.5배의 성능 향상과 static final 필드로 끄집어내서 코드가 훨씬 잘 드러난다.  혹시나 이 코드가 사용되지 않을경우 불필요한 초기화를 한것이므로 코틀린의 경우 by lazy와 같은 지연초기화 코드를 통해 성능을 개선하기 바란다.


1. 불필요한 객체생성 (KeySet)

Map인터페이스의 KeySet메서드는 Map객체 안에 키를 전부담은 Set을 반환한다. KeySet은 기능적으로는 모두 똑같은 Set을 반환한다. 따라서 반환된 객체 중 하나를 변경하게된다면 모든 Set의 객체가 변경되는데, Set이 뷰객체를 여러개 만들어 되지만 그럴필요가 없다.

2. 불필요한 객체생성 (박싱타입)

오토박싱을 통해 불필요한 객체를 만들수도 있다. 오토박싱은 기본타입과 그에 대응하는 박싱된 기본타입의 구분을 흐려주지만 완전히 없애주는것은 아니다.


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


불필요한 박싱 타입 만들지 않음으로 6.5초를 0.8초까지 단축 가능하다. 

불필요한 박싱타입을 생성하지 말고 기본타입으로 생성해라. 또한 의도치 않은 오토박싱이 숨어 들지 않도록 주의해야 합니다.